Overview
在本指南中,您可以学习;了解如何使用MongoDB Extension for Hibernate ORM 在字符串字段上调用 Hibernate Query Language (HQL) 字符串函数。字符串函数允许您在查询中测量、重新格式化和组合字符串值。
您可以在 SELECT 子句中调用每个函数。 Hibernate ORM 扩展将每个函数调用转换为 $project 阶段的MongoDB聚合表达式。由于 Hibernate ORM 扩展不支持将函数调用作为计算表达式的操作数,因此您无法将字符串函数与算术操作符组合使用。
Hibernate ORM 扩展支持以下字符串函数:
function | MongoDB翻译 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 根据 $ 范围和 $reduce 计算 |
注意
不支持的字符串函数
Hibernate ORM 扩展不支持HQL position()、overlay()、left()、right() 和 collate() 字符串函数。调用这些函数之一的查询会抛出 FeatureNotSupportedException。
要使用不支持的字符串函数,请调用 createNativeQuery() 方法并在MongoDB查询语言声明中包含相关操作符。要学习;了解更多信息,请参阅执行原生数据库查询指南。
样本数据
The examples in this guide use the Movie entity, which represents the sample_mflix.movies collection from the Atlas sample datasets. The Movie entity has the following definition:
import com.mongodb.hibernate.annotations.ObjectIdGenerator; import org.bson.types.ObjectId; import java.time.Instant; import java.util.List; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; private Awards awards; private List<Comment> comments; public Movie(String title, String plot, int year, List<String> cast, List<String> directors, Instant released, Awards awards) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; this.directors = directors; this.released = released; this.awards = awards; } public Movie() { } public ObjectId getId() { return id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPlot() { return plot; } public void setPlot(String plot) { this.plot = plot; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public List<String> getCast() { return cast; } public void setCast(List<String> cast) { this.cast = cast; } public List<String> getDirectors() { return directors; } public void setDirectors(List<String> directors) { this.directors = directors; } public Awards getAwards() { return awards; } public void setAwards(Awards awards) { this.awards = awards; } public Instant getReleased() { return released; } public void setReleased(Instant released) { this.released = released; } public List<Comment> getComments() { return comments; } public void setComments(List<Comment> comments) { this.comments = comments; } }
学习如何创建使用 MongoDB Extension for Hibernate ORM 与此 MongoDB 示例集合交互的 Java 应用程序,请参阅 入门 教程。
本指南中的示例使用 Movie 实体的 title字段,其中存储了 String 值。
测量字符串的长度
length(str) 函数返回字符串中的字符数。您也可以将此函数称为 character_length(str) 或 char_length(str),它们是同一函数的别名。由于 Hibernate ORM 扩展会将调用转换为 $strLenCP操作符,因此该函数计算的是 Unicode 代码点而不是字节数。
以下示例返回 sample_mflix.movies集合中 "The Hunger Games" 电影的标题以及标题的长度:
var lengthResult = session.createQuery( "select title, length(title) as titleLength from Movie where title = :title", Object[].class) .setParameter("title", "The Hunger Games") .getResultList(); for (var row : lengthResult) { System.out.println("Title: " + row[0] + ", Length: " + row[1]); }
var lengthResult = entityManager.createQuery( "select m.title, length(m.title) as titleLength from Movie m where m.title = :title", Object[].class) .setParameter("title", "The Hunger Games") .getResultList(); for (var row : lengthResult) { System.out.println("Title: " + row[0] + ", Length: " + row[1]); }
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段:
{ "$project": { "title": true, "titleLength": { "$strLenCP": "$title" }, "_id": 0 } }
更改字符串的大小写
upper(str) 和 lower(str) 函数将字符串转换为大写或小写。
以下示例以大写形式返回 "The Hunger Games" 电影的标题:
var upperResult = session.createQuery( "select upper(title) as upperTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var upperTitle : upperResult) { System.out.println("Uppercase Title: " + upperTitle); }
var upperResult = entityManager.createQuery( "select upper(m.title) as upperTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var upperTitle : upperResult) { System.out.println("Uppercase Title: " + upperTitle); }
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段:
{ "$project": { "upperTitle": { "$toUpper": "$title" }, "_id": 0 } }
连接字符串
concat(x, y) 函数将两个或多个值连接成一个字符串。 Hibernate ORM 扩展会在连接之前将每个操作数转换为字符串,以便您可以连接数值或将数值连接到字符串值。
以下示例在 "The Hunger Games" 电影的标题后附加一个点:
var concatResult = session.createQuery( "select concat(title, '!') as excitedTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var excitedTitle : concatResult) { System.out.println("Concatenated Title: " + excitedTitle); }
var concatResult = entityManager.createQuery( "select concat(m.title, '!') as excitedTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var excitedTitle : concatResult) { System.out.println("Concatenated Title: " + excitedTitle); }
提示
您还可以使用双管操作符(||) 连接两个值。以下查询与前面的示例等效:
"select title || '!' as excitedTitle from Movie where title = :title"
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段:
{ "$project": { "excitedTitle": { "$concat": [ { "$toString": "$title" }, { "$toString": "!" } ] }, "_id": 0 } }
提取子字符串
substring(str, start) 函数返回字符串中从 start 位置开始的部分。 start 位置从 1 开始,因此字符串中的第一个字符位于位置 1。要将结果限制为固定字符数,请以 substring(str, start, length) 形式调用该函数。
如果传递 0 的 start 位置或负值,则 Hibernate ORM 扩展会从字符串的开头读取。如果还传递了 length,则扩展将从返回的长度中减去第一个位置之前的字符。示例,substring(str, -1, 3) 返回一个字符,substring(str, 0, 3) 返回两个字符。
以下示例返回 "The Hunger Games" 电影标题的前六个字符:
var substringResult = session.createQuery( "select substring(title, 1, 6) as titlePrefix from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var titlePrefix : substringResult) { System.out.println("Title Prefix: " + titlePrefix); }
var substringResult = entityManager.createQuery( "select substring(m.title, 1, 6) as titlePrefix from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var titlePrefix : substringResult) { System.out.println("Title Prefix: " + titlePrefix); }
查找子字符串
locate(pattern, str) 函数返回字符串中首次出现 pattern 的从一开始的位置;如果字符串不包含模式,则返回 0。
要从特定位置开始搜索,请以 locate(pattern, str, start) 形式调用该函数。由于 start 位置是从 1 开始的,因此字符串中的第一个字符位于 1 位置。 start 的 0 值或负数会从位置 1 开始搜索。
以下示例返回子字符串 "Hunger" 在 "The Hunger Games" 电影标题中的位置:
var locateResult = session.createQuery( "select locate('Hunger', title) as position from Movie where title = :title", Integer.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var position : locateResult) { System.out.println("Position: " + position); }
var locateResult = entityManager.createQuery( "select locate('Hunger', m.title) as position from Movie m where m.title = :title", Integer.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var position : locateResult) { System.out.println("Position: " + position); }
替换子字符串
replace(str, pattern, replacement) 函数将字符串中每次出现的 pattern 替换为 replacement。 Hibernate ORM 扩展会将调用转换为 $replaceAll操作符。所有三个参数都必须是字符串。
以下示例将 "The Hunger Games" 电影标题中的子字符串 "Hunger" 替换为 "Video":
var replaceResult = session.createQuery( "select replace(title, 'Hunger', 'Video') as newTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var newTitle : replaceResult) { System.out.println("New Title: " + newTitle); }
var replaceResult = entityManager.createQuery( "select replace(m.title, 'Hunger', 'Video') as newTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var newTitle : replaceResult) { System.out.println("New Title: " + newTitle); }
从字符串中修剪字符
trim(str) 函数删除字符串中的前导和尾随空格。要仅删除字符串一端的字符,请使用 trim(leading char from str) 或 trim(trailing char from str)。要从字符串两端删除空格以外的字符,请使用 both 和 from 关键字指定该字符,如 trim(both char from str) 所示。
以下示例从 "The Hunger Games" 电影标题中删除前导 "T" 字符:
var trimResult = session.createQuery( "select trim(leading 'T' from title) as trimmedTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var trimmedTitle : trimResult) { System.out.println("Trimmed Title: " + trimmedTitle); }
var trimResult = entityManager.createQuery( "select trim(leading 'T' from m.title) as trimmedTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var trimmedTitle : trimResult) { System.out.println("Trimmed Title: " + trimmedTitle); }
Hibernate ORM 扩展将前面的查询转换为以下 $project 阶段:
{ "$project": { "trimmedTitle": { "$ltrim": { "chars": "T", "input": "$title" } }, "_id": 0 } }
填充字符串
pad(str with length leading) 和 pad(str with length trailing) 函数通过在字符串 str 的开头或结尾添加空格,将字符串扩展为指定的 length。要使用空格以外的字符,请在方向后指定该字符,如 pad(str with 20 leading char)。
您还可以调用 lpad(str, length, padding) 和 rpad(str, length, padding) 函数,用可以包含多个字符的值填充字符串。 Hibernate ORM 扩展根据需要多次重复填充值,并将其截断以达到目标长度。示例,lpad('x', 6, 'ab') 会返回 "ababax"。
在这些情况下,填充的行为如下:
如果目标长度短于字符串,Hibernate ORM 扩展会删除目标长度之后的尾随字符,从而将字符串截断为目标长度。
如果目标长度为负数,则函数返回空字符串。
如果填充值为空字符串,则该函数返回原始字符串。
以下示例使用前导星号将 "The Hunger Games" 电影的标题填充为 20 个字符:
var padResult = session.createQuery( "select pad(title with 20 leading '*') as paddedTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var paddedTitle : padResult) { System.out.println("Padded Title: " + paddedTitle); }
var padResult = entityManager.createQuery( "select pad(m.title with 20 leading '*') as paddedTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var paddedTitle : padResult) { System.out.println("Padded Title: " + paddedTitle); }
重复字符串
repeat(str, count) 函数返回一个字符串,其中包含 str 的 count 个副本。
以下示例返回 "The Hunger Games" 电影的标题,重复两次:
var repeatResult = session.createQuery( "select repeat(title, 2) as repeatedTitle from Movie where title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var repeatedTitle : repeatResult) { System.out.println("Repeated Title: " + repeatedTitle); }
var repeatResult = entityManager.createQuery( "select repeat(m.title, 2) as repeatedTitle from Movie m where m.title = :title", String.class) .setParameter("title", "The Hunger Games") .getResultList(); for (var repeatedTitle : repeatResult) { System.out.println("Repeated Title: " + repeatedTitle); }
更多信息
要学习;了解有关创建查询筛选器和在查询语句中使用操作符的更多信息,请参阅“指定查询”指南。
要学习;了解如何在查询中调用日期时间函数,请参阅“在查询中使用日期时间函数”指南。
要了解有关使用 HQL 和 JPQL 运行查询的更多信息,请参阅 Hibernate ORM 文档中的 Hibernate 查询语言指南。