对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Docs 菜单

在查询中使用字符串函数

在本指南中,您可以学习;了解如何使用MongoDB Extension for Hibernate ORM 在字符串字段上调用 Hibernate Query Language (HQL) 字符串函数。字符串函数允许您在查询中测量、重新格式化和组合字符串值。

您可以在 SELECT 子句中调用每个函数。 Hibernate ORM 扩展将每个函数调用转换为 $project 阶段的MongoDB聚合表达式。由于 Hibernate ORM 扩展不支持将函数调用作为计算表达式的操作数,因此您无法将字符串函数与算术操作符组合使用。

Hibernate ORM 扩展支持以下字符串函数:

function
MongoDB翻译

length(), character_length() , char_length()

upper()

lower()

concat(), ||

substring()

locate()

replace()

trim()

pad(), lpad() , rpad()

repeat()

根据 $ 范围和 $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;
@Entity
@Table(name = "movies")
public class Movie {
@Id
@ObjectIdGenerator
private ObjectId id;
private String title;
private String plot;
private int year;
private List<String> cast;
private List<String> directors;
private Instant released;
@Embedded
private Awards awards;
@OneToMany(mappedBy = "movie", fetch = FetchType.LAZY)
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 查询语言指南。