文档菜单
文档首页
/ / /
Rust 驱动
/ / /

搜索文本

本页内容

  • 概述
  • 示例用例的数据样本
  • 文本索引
  • 文本搜索
  • 搜索一个词
  • 搜索一个短语
  • 排除搜索中的词
  • 按相关性排序
  • 聚合
  • 匹配搜索词
  • 按相关性排序
  • 更多信息
  • API 文档

在本指南中,您可以了解如何使用 Rust 驱动程序运行文本搜索。文本搜索允许您高效地查询具有字符串值的字段。

重要

MongoDB 文本搜索与更强大的 Atlas Search 功能不同。要了解更多信息,请参阅Atlas Search 文档.

本指南包括以下部分

  • 示例用例的数据样本 展示了文本搜索示例使用的样本数据

  • 文本索引 描述了如何在字符串值字段上创建文本索引

  • 文本搜索 描述了如何使用不同的搜索标准执行文本搜索

  • 聚合 描述了如何使用聚合管道执行文本搜索

  • 更多信息 提供了本指南中提到的类型和方法的相关资源链接和 API 文档

本指南中的示例使用以下内容Dish 结构作为 menu 集合中文档的模型

#[derive(Serialize, Deserialize, Debug)]
struct Dish {
name: String,
description: String,
}

以下示例使用了以下样本文档,描述了您可以在餐厅订餐的菜品

{ "name": "Shepherd’s Pie", "description": "A vegetarian take on the classic dish that uses lentils as a base. Serves 2." },
{ "name": "Green Curry", "description": "A flavorful Thai curry, made vegetarian with tofu. Vegetarian and vegan friendly." },
{ "name": "Herbed Branzino", "description": "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4." },
{ "name": "Kale Tabbouleh", "description": "A bright, herb-based salad. A perfect starter for vegetarians and vegans." },
{ "name": "Garlic Butter Trout", "description": "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2." }

在执行文本搜索之前,您必须在集合上创建一个 文本索引。文本索引指定可以执行文本搜索的字符串或字符串数组字段。

本指南中的示例在 menu 集合中文档的 description 字段上执行文本搜索。要启用 description 字段的文本搜索,请创建如下代码所示的文本索引

let index = IndexModel::builder()
.keys(doc! { "description": "text" })
.build();
let idx_res = my_coll.create_index(index).await?;

文本搜索检索包含指定 术语短语 的索引字段值的文档。术语是一系列不包括空白字符的字符。短语是一系列可以包含任意数量空白字符的术语。

要执行文本搜索,请将 $text 评估查询运算符包含在查询过滤器中,后跟 $search 字段。$text 运算符指定您正在对文本索引字段执行文本搜索。$search 字段指定在文本索引字段或字段中搜索的术语或短语。

文本搜索的查询过滤器使用以下格式

let filter = doc! { "$text": { "$search": "<search term or phrase>" } };

要搜索一个术语,请在查询过滤器中将术语指定为字符串。要搜索多个术语,请用空格分隔每个术语。

注意

当搜索多个术语时,find()方法返回任何包含至少一个术语的文本索引字段或字段的文档。

例如,如果您的搜索术语是"one two three",MongoDB将返回包含索引字段包含"one""two""three"或这些术语中多个术语的文档。

以下示例演示了在包含术语"herb"description字段中搜索文档。

let filter = doc! { "$text": { "$search": "herb" } };
let mut cursor = my_coll.find(filter).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Dish { name: "Kale Tabbouleh", description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans." }
Dish { name: "Herbed Branzino", description: "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4." }

提示

即使搜索术语是"herb",文本搜索也会匹配包含"herbs"description字段的文档。这是因为MongoDB文本索引使用后缀词干提取来匹配类似词语。有关MongoDB如何匹配术语的更多信息,请参阅服务器手册中的索引条目

要搜索短语,请在查询过滤器中使用转义引号指定短语

let filter = doc! { "$text": { "$search": "\"<some phrase>\"" } };

如果您没有在短语周围添加转义引号,则搜索将执行词搜索。

以下示例搜索包含短语 "serves 2" 的文档

let filter = doc! { "$text": { "$search": "\"serves 2\"" } };
let mut cursor = my_coll.find(filter).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Dish { name: "Shepherd’s Pie", description: "A vegetarian take on the classic dish that uses lentils as a base. Serves 2." }
Dish { name: "Garlic Butter Trout", description: "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2." }

要指定您希望从文本搜索中排除的术语或短语,请在查询过滤器中使用减号作为前缀

let filter = doc! { "$text": { "$search": "<term> -<excluded term>" } };

重要

您必须搜索至少一个术语或短语,才能从搜索中排除其他术语。如果您只排除术语,则搜索不会返回任何文档。

以下示例在描述字段包含术语“vegan”但不含术语“tofu”的文档中进行搜索

let filter = doc! { "$text": { "$search": "vegan -tofu" } };
let mut cursor = my_coll.find(filter).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Dish { name: "Kale Tabbouleh", description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans." }

文本搜索会分配一个数值文本得分来指示每个结果与您的查询过滤器中的字符串的匹配程度。得分越高,表示结果与您的查询越相关。要在输出中显示文本得分,请使用投影检索元数据中的textScore字段。您可以通过指定对textScore元数据字段的排序来按降序排序文本得分。

此示例执行以下操作

  • 在描述字段包含术语“vegetarian”的文档中进行搜索

  • 按文本得分降序排序结果

  • 输出中仅包含 名称分数 字段。

let filter = doc! { "$text": { "$search": "vegetarian" } };
let sort = doc! { "score": { "$meta": "textScore" } };
let projection =
doc! {
"_id": 0,
"name": 1,
"score": { "$meta": "textScore" }
};
let doc_coll: Collection<Document> = my_coll.clone_with_type();
let mut cursor = doc_coll.find(filter)
.sort(sort)
.projection(projection)
.await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Document({"name": String("Green Curry"), "score": Double(0.9166666666666667)})
Document({"name": String("Kale Tabbouleh"), "score": Double(0.5625)})
Document({"name": String("Shepherd’s Pie"), "score": Double(0.5555555555555556)})

您可以将 $text 评估查询操作符包含在 $match 聚合阶段中,以在聚合管道中执行文本搜索。

以下部分展示了如何通过使用聚合管道而不是 find() 方法来执行文本搜索。

以下示例使用聚合来搜索包含 描述 字段中包含术语 "herb" 的文档。

let match_stage = doc! { "$match": { "$text": { "$search": "herb" } } };
let mut cursor = my_coll.aggregate([match_stage]).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Document({"_id": ObjectId("..."), "name": String("Kale Tabbouleh"), "description": String("A bright, herb-based salad. A perfect starter for vegetarians and vegans.")})
Document({"_id": ObjectId("..."), "name": String("Herbed Branzino"), "description": String("Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4.")})

此示例使用聚合执行以下操作

  • 在描述字段包含术语“vegetarian”的文档中进行搜索

  • 按文本得分降序排序结果

  • 输出中仅包含 名称分数 字段。

let match_stage = doc! { "$match": { "$text": { "$search": "vegetarian" } } };
let sort_stage = doc! { "$sort": { "score": { "$meta": "textScore" } } };
let proj_stage =
doc! { "$project": {
"_id": 0,
"name": 1,
"score": { "$meta": "textScore" }
} };
let pipeline = [match_stage, sort_stage, proj_stage];
let mut cursor = my_coll.aggregate(pipeline).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Document({"name": String("Green Curry"), "score": Double(0.9166666666666667)})
Document({"name": String("Kale Tabbouleh"), "score": Double(0.5625)})
Document({"name": String("Shepherd’s Pie"), "score": Double(0.5555555555555556)})

有关使用 find() 方法的可运行示例,请参阅查找多个文档 用例。

要了解更多关于本指南中所述的操作的信息,请参阅以下文档

要了解本指南中提到的方法和类型,请参阅以下 API 文档

返回

打开变更流