搜索文本
概述
在本指南中,您可以学习如何运行文本搜索.
重要
MongoDB文本搜索与Atlas Search不同。
示例数据
本指南中的示例使用以下Dish
结构作为 menu
集合中文档的模型
type Dish struct { Name string Description string }
要运行本指南中的示例,请使用以下代码片段将样本数据加载到 db.menu
集合中
coll := client.Database("db").Collection("menu") docs := []interface{}{ Dish{Name: "Shepherd’s Pie", Description: "A vegetarian take on the classic dish that uses lentils as a base. Serves 2."}, Dish{Name: "Green Curry", Description: "A flavorful Thai curry, made vegetarian with fried tofu. Vegetarian and vegan friendly."}, Dish{Name: "Herbed Whole Branzino", Description: "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4."}, Dish{Name: "Kale Tabbouleh", Description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans."}, Dish{Name: "Garlic Butter Trout", Description: "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2."}, } result, err := coll.InsertMany(context.TODO(), docs)
每个文档包含餐厅菜单中菜肴的 name
和 description
。
提示
不存在的数据库和集合
当您执行写操作而所需的数据库和集合不存在时,服务器会隐式创建它们。
文本索引
在运行文本搜索之前,您必须创建一个文本索引。文本索引指定了要运行文本搜索的字符串或字符串数组字段。
以下部分中的示例在menu
集合中文档的description
字段上运行文本搜索。为了在description
字段上启用文本搜索,创建以下片段的文本索引:
model := mongo.IndexModel{Keys: bson.D{{"description", "text"}}} name, err := coll.Indexes().CreateOne(context.TODO(), model) if err != nil { panic(err) } fmt.Println("Name of index created: " + name)
文本搜索
文本搜索可以检索包含索引字段中的术语或短语的文档。术语是一系列字符,不包含空白字符。短语是一系列术语,包含任意数量的空白字符。
要执行文本搜索,请使用查询过滤器中的$text
评估查询运算符,后跟$search
字段。该$text
运算符在文本索引字段上执行文本搜索。该$search
字段指定在文本索引字段中搜索的文本。
文本搜索的查询过滤器使用以下格式
filter := bson.D{{"$text", bson.D{{"$search", "<text to search>"}}}}
通过一个词搜索
要搜索一个词,请在查询过滤器中将词指定为字符串。要搜索多个词,请在字符串中用空格分隔每个词。
注意
当搜索多个词时,Find()
方法返回包含至少一个词的文本索引字段的文档。
示例
以下示例运行了一个包含词 "herb" 的描述的文本搜索
filter := bson.D{{"$text", bson.D{{"$search", "herb"}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Kale Tabbouleh","description":"A bright, herb-based salad. A perfect starter for vegetarians and vegans."} {"name":"Herbed Whole Branzino","description":"Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4."}
提示
尽管搜索词是 "herb",但该方法也匹配包含 "herbs" 的描述,因为 MongoDB 文本索引使用词尾词干化来匹配类似单词。有关 MongoDB 如何匹配词的更多信息,请参阅索引条目。
通过短语搜索
要搜索一个短语,请在查询过滤器中将短语指定为带有转义引号的字符串。如果您不在短语周围添加转义引号,则 Find()
方法将运行 词搜索。
提示
转义引号是一个反斜杠字符后跟一个双引号字符。
示例
以下示例运行文本搜索,查找包含短语 "serves 2" 的描述
filter := bson.D{{"$text", bson.D{{"$search", "\"serves 2\""}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Shepherd's Pie","description":"A vegetarian take on the classic dish that uses lentils as a base. Serves 2."} {"name":"Garlic Butter Trout","description":"Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2."}
排除特定词的搜索
对于您想从文本搜索中排除的每个术语或短语,请将带有连字符前缀的术语或短语作为字符串指定在查询过滤器中。
重要
如果您想排除搜索中的术语,则必须至少搜索一个术语。如果您不搜索任何术语,则 Find()
方法不会返回任何文档。
示例
以下示例运行文本搜索,查找包含术语 "vegan",但不包含术语 "tofu" 的描述
filter := bson.D{{"$text", bson.D{{"$search", "vegan -tofu"}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Kale Tabbouleh","description":"A bright, herb-based salad. A perfect starter for vegetarians and vegans."}
按相关性排序
文本搜索为每个结果分配一个数值文本得分,以指示每个结果与查询过滤器中的字符串匹配的紧密程度。要显示输出中的文本得分,请使用投影来检索textScore
元数据。您可以通过指定对textScore
元数据的排序来按降序排序文本得分。
示例
以下示例执行以下操作
运行包含术语“素食”的描述的文本搜索
根据文本得分降序排序结果
最终输出文档中仅包含
name
和score
字段
filter := bson.D{{"$text", bson.D{{"$search", "vegetarian"}}}} sort := bson.D{{"score", bson.D{{"$meta", "textScore"}}}} projection := bson.D{{"name", 1}, {"score", bson.D{{"$meta", "textScore"}}}, {"_id", 0}} opts := options.Find().SetSort(sort).SetProjection(projection) cursor, err := coll.Find(context.TODO(), filter, opts) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Green Curry","score":0.8999999999999999} {"name":"Kale Tabbouleh","score":0.5625} {"name":"Shepherd's Pie","score":0.5555555555555556}
聚合
您还可以在$match阶段包含$text
评估查询运算符,以在聚合管道中执行文本搜索。
匹配搜索词
以下示例运行了一个包含词 "herb" 的描述的文本搜索
matchStage := bson.D{{"$match", bson.D{{"$text", bson.D{{"$search", "herb"}}}}}} cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage}) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Kale Tabbouleh","description":"A bright, herb-based salad. A perfect starter for vegetarians and vegans."} {"name":"Herbed Whole Branzino","description":"Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4."}
按相关性排序
以下示例执行以下操作
运行包含术语“素食”的描述的文本搜索
根据文本得分降序排序结果
最终输出文档中仅包含
name
和score
字段
matchStage := bson.D{{"$match", bson.D{{"$text", bson.D{{"$search", "vegetarian"}}}}}} sortStage := bson.D{{"$sort", bson.D{{"score", bson.D{{ "$meta", "textScore" }}}}}} projectStage := bson.D{{"$project", bson.D{{"name", 1}, {"score", bson.D{{ "$meta", "textScore" }}}, {"_id", 0}}}} cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage, sortStage, projectStage}) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Green Curry","score":0.8999999999999999} {"name":"Kale Tabbouleh","score":0.5625} {"name":"Shepherd's Pie","score":0.5555555555555556}
附加信息
有关所提操作的更多信息,请参阅以下指南
API 文档
要了解更多关于本指南中讨论的任何方法或类型的信息,请参阅以下 API 文档