Spring Data MongoDB 教程

全文查询

从 MongoDB 2.6 版开始,您可以使用 $text 运算符运行全文查询。TextQuery 和 TextCriteria 中提供了特定于全文查询的方法和操作。

全文搜索

在实际使用全文搜索之前,必须正确设置搜索索引。有关如何创建索引结构的详细信息,请参阅文本索引。以下示例显示了如何设置全文搜索:

db.foo.createIndex({
   title : "text",
   content : "text"
},
{
   weights : {
       title : 3
   }
})

可以像下面一样定义和运行搜索 “咖啡蛋糕” 的查询:

Query query = TextQuery
   .queryText(new TextCriteria().matchingAny("coffee", "cake"));

List<Document> page = template.find(query, Document.class);

要根据权重按相关性排序结果,请使用 TextQuery.sortByScore():

Query query = TextQuery
   .queryText(new TextCriteria().matchingAny("coffee", "cake"))
   // (1) 使用 score 属性按相关性对结果进行排序,这会触发.sort({'score': {'$meta': 'textScore'}})
   .sortByScore()
   // (2) 使用TextQuery.includeScore()将计算出的相关度包括在结果的 Document 中
   .includeScore();

List<Document> page = template.find(query, Document.class);

你可以通过在搜索词前加上 “-” 或者使用 notMatching 来排除搜索词,如下例所示(注意,这两行有相同的效果,因此是多余的):

// 搜索 “coffee” 而不是 “cake”
TextQuery.queryText(new TextCriteria().matching("coffee").matching("-cake"));
TextQuery.queryText(new TextCriteria().matching("coffee").notMatching("cake"));

TextCriteria.matching() 按原样使用提供的术语。。因此,你可以通过把短语放在双引号之间(例如,\"coffee cake\")或使用 TextCriteria.phrase 来定义短语。下面的例子显示了定义短语的两种方式:

// 搜索短语 'coffee cake'
TextQuery.queryText(new TextCriteria().matching("\"coffee cake\""));
TextQuery.queryText(new TextCriteria().phrase("coffee cake"));

注意:你可以通过使用 TextCriteria 上的相应方法为 $caseSensitive 和 $diacriticSensitive 设置标志。请注意,这两个可选的标志在 MongoDB 3.2 中被引入,除非明确设置,否则不包括在查询中。

示例

(1)创建 Book 实体,代码如下:

package com.hxstrive.springdata.mongodb.entity;

import lombok.Builder;
import lombok.Data;
import lombok.ToString;

@Data
@Builder
@ToString
public class Book {
   /** 书籍ID */
   private int id;
   /** 书籍名称 */
   private String name;
   /** 书籍价格 */
   private float price;
   /** 书籍描述信息 */
   private String summary;
}

(2)客户端代码,演示怎样使用全文索引,代码如下:

package com.hxstrive.springdata.mongodb.query;

import com.hxstrive.springdata.mongodb.entity.Book;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.TextIndexDefinition;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.TextCriteria;
import org.springframework.data.mongodb.core.query.TextQuery;
import java.util.List;

@SpringBootTest
public class FullTextQueryTest {

   @Autowired
   private MongoTemplate mongoTemplate;

   @BeforeEach
   public void init() {
       // 删除集合,清空数据
       mongoTemplate.dropCollection(Book.class);

       // 准备数据
       mongoTemplate.insert(Book.builder().id(100).name("NoSQL数据库实战派:Redis + MongoDB + HBase")
               .price(118.0f)
               .summary("本书介绍了 NoSQL 数据库生态圈体系,包括 Redis、MongoDB 和 HBase,内容涉及开发、运维、管理与架构。")
               .build());
       mongoTemplate.insert(Book.builder().id(200).name("MongoDB 权威指南 第3版")
               .price(108.7f)
               .summary("本书是由 MongoDB 团队成员撰写的入门指南,涵盖从开发到部署的各个方面,内容适合MongoDB 4.2及以上版本。")
               .build());
       mongoTemplate.insert(Book.builder().id(300).name("MongoDB 进阶与实战:微服务整合、性能优化、架构管理")
               .price(118.0f)
               .summary("本书围绕如何用好MongoDB这个复杂命题,利用大部分篇幅讲述了MongoDB在应用开发方面的各种进阶技巧," +
                       "同时也介绍了MongoDB 4.0版本的事务特性及微服务相关的技术范例。")
               .build());

       // 进行全文索引,必须创建索引
       // 下面在 summary 字段上面创建索引
       mongoTemplate.indexOps(Book.class).ensureIndex(
               TextIndexDefinition.builder().onField("summary").build());
   }

   @Test
   public void contextLoads() {
       // 查询 summary 字段中包含 MongoDB 单词的记录
       Query query = TextQuery.queryText(new TextCriteria().matchingAny("MongoDB"));
       List<Book> bookList = mongoTemplate.find(query, Book.class);
       for(Book book : bookList) {
           System.out.println(book);
       }
       // 根据搜索只输出了 ID 为 100 和 200 的数据,因为它们的 summary 中包含了 MongoDB 单词
       // 而 ID 为 300 的记录中有 MongoDB,但是没有使用空格分开,不算单词,也就搜索不到
   }

   @Test
   public void contextLoads2() {
       // 查询 summary 字段中包含 MongoDB 或者 HBase 单词的记录
       Query query = TextQuery.queryText(new TextCriteria().matchingAny("MongoDB", "HBase"));
       List<Book> bookList = mongoTemplate.find(query, Book.class);
       for(Book book : bookList) {
           System.out.println(book);
       }
   }

   @Test
   public void contextLoads3() {
       // 搜索短语 'MongoDB 和 HBase',由多个单词组成
       List<Book> bookList = mongoTemplate.find(
               TextQuery.queryText(new TextCriteria().matching("\"MongoDB 和 HBase\"")), Book.class);
       for(Book book : bookList) {
           System.out.println(book);
       }

       System.out.println("=================分割线==================");

       // 等价
       bookList = mongoTemplate.find(
               TextQuery.queryText(new TextCriteria().matchingPhrase("MongoDB 和 HBase")), Book.class);
       for(Book book : bookList) {
           System.out.println(book);
       }
   }

}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号