Overview
在本指南中,您可以了解如何使用 Search 生成器,通过 MongoDB .NET/C# 驱动程序构建一个聚合管道阶段。
要了解有关 $search 管道阶段的更多信息,请参阅 $search。
注意
Atlas和 Community Edition 版本要求
$search 聚合管道操作符仅适用于在运行 MongoDB v4.2 或更高版本的MongoDB Atlas集群上托管的集合,或者运行 MongoDB v8.2 或更高版本的MongoDB Community Edition集群上托管的集合。集合必须包含在MongoDB 搜索索引中。要了解有关此操作符所需设置和功能的更多信息,请参阅MongoDB 搜索文档。
样本数据
本指南中的示例使用 sample_mflix数据库中的 movies集合。此集合中的文档包含有关电影的信息,包括标题、情节、类型和评级。以下 Movie 类对此集合中的文档进行建模:
[] public class Movie { [] public ObjectId Id { get; set; } public string Title { get; set; } = null!; public string Plot { get; set; } = null!; public string[] Genres { get; set; } = null!; public int Year { get; set; } public string Rated { get; set; } = null!; public Imdb Imdb { get; set; } = null!; [] public float[] PlotEmbedding { get; set; } = null!; public double Score { get; set; } [] public string PaginationToken { get; set; } = null!; }
Movie 类引用以下 Imdb 类,该类对每个文档中的嵌套 imdb字段进行建模:
[] public class Imdb { public double Rating { get; set; } public int Votes { get; set; } public int Id { get; set; } }
注意
示例数据中的驼峰命名字段名称
movies 集合中的文档使用驼峰命名约定。本指南中的示例使用 ConventionPack 将集合中的字段反序列化为 Pascal 语句,然后映射到 Movie 类中的属性。
如需了解有关自定义序列化的更多信息,请参阅自定义序列化。
本指南中的一些示例使用了相关章节中介绍的其他集合和模型类。 所有集合均来自Atlas提供的示例数据集。请参阅.NET/ C#驱动程序入门,学习;了解如何创建免费的MongoDB 集群并加载此示例数据。
注意
示例数据中不一致的字段类型
movies集合中的某些文档将 imdb.rating 和 imdb.votes 字段存储为字符串而不是数字。如果您在模型类中将这些字段定义为 double 或 int,则驱动程序在反序列化这些文档时会抛出 FormatException。
要处理具有混合字段类型的文档,实现接受多个BSON 类型的自定义序列化器,并将其与 [BsonSerializer] 属性一起应用受影响的属性:
[] public class Imdb { [] public double Rating { get; set; } [] public int Votes { get; set; } public int Id { get; set; } }
要学习;了解如何实现FlexibleDoubleSerializer 等自定义序列化器,请参阅自定义序列化器。
创建MongoDB搜索索引
在对Atlas集合执行搜索之前,必须先在该集合上创建MongoDB 搜索索引。MongoDB搜索索引是一种以可搜索格式对数据进行分类的数据结构。
要学习;了解如何创建MongoDB搜索索引,请参阅创建MongoDB搜索索引指南。
MongoDB 搜索 操作符和收集器
Search 类包含可用于执行 $search 操作的方法。有关可用 $search 操作符和收集器的完整列表,请参阅Atlas操作符和收集器指南。
自动完成(Autocomplete)
使用 Autocomplete() 方法,搜索包含不完整输入字符串中的字符序列的单词或短语。
以下示例对 title字段执行自动完成查询,查找以 string "Gravity" 开头的文本:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Autocomplete(m => m.Title, "Gravity"), indexName: "movietitles") .ToList();
... { "_id" : ObjectId("..."), "title" : "Gravity", "plot" : "...", "genres" : ["Drama", "Sci-Fi", "Thriller"], "year" : 2013, "rated" : "PG-13", "imdb" : { "rating" : 7.7, "votes" : "...", "id" : "..." } } ...
要了解有关 autocomplete 操作符的更多信息,请参阅 autocomplete Atlas 指南。
注意
自动完成查询的索引
您必须创建支持自动完成的MongoDB搜索索引,才能成功执行自动完成查询。要学习更多信息,请参阅Atlas文档中的如何对字段进行索引以支持自动完成。
创建MongoDB Search索引后,必须将索引名称传递给 Autocomplete() 方法,如前面的示例所示。
多个子句
使用 Compound() 方法将两个或更多操作符组合到单次搜索中。
以下示例在 movies 集合中搜索符合以下所有条件的任何文档:
文档上存在
imdb.rating字段rated字段值不是"G"year字段的值大于 2000
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Compound() .Must(Builders<Movie>.Search.Exists(m => m.Imdb.Rating)) .MustNot(Builders<Movie>.Search.Equals(m => m.Rated, "G")) .Must(Builders<Movie>.Search.Range(m => m.Year, SearchRangeBuilder.Gt(2000)))) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Inception", "plot" : "...", "genres" : ["Action", "Adventure", "Sci-Fi"], "year" : 2010, "rated" : "PG-13", "imdb" : { "rating" : 8.8, "votes" : "...", "id" : "..." } } ...
要了解有关 compound 操作符的更多信息,请参阅 compound Atlas 指南。
嵌入式文档
使用 EmbeddedDocument() 方法对字段的数组值中的文档执行搜索操作。
注意
需要嵌入式文档索引
要对嵌入式文档进行Atlas Search ,您必须在数组字段上创建 embeddedDocument 索引。
要了解如何定义 embeddedDocument 索引,请参阅 Atlas 文档中的为 embeddedDocument 类型定义索引。
此示例使用 sample_restaurants数据库中的 restaurants集合。以下类对该集合中的文档进行建模:
[] public class Restaurant { [] public ObjectId Id { get; set; } public string Name { get; set; } = null!; public string Cuisine { get; set; } = null!; public string Borough { get; set; } = null!; public List<GradeEntry> Grades { get; set; } = null!; }
[] public class GradeEntry { public string Grade { get; set; } = null!; public int? Score { get; set; } }
以下示例在该集合搜索 grades数组包含 grade字段值为 "A" 的条目的所有餐厅:
var result = restaurantsCollection.Aggregate() .Search(Builders<Restaurant>.Search.EmbeddedDocument( r => r.Grades, Builders<GradeEntry>.Search.Equals(g => g.Grade, "A") ), indexName: "restaurantsembedded").ToList();
... { "_id" : ObjectId("..."), "name" : "Riviera Caterer", "cuisine" : "American", "borough" : "Brooklyn", "grades" : [{ "grade" : "A", "score" : 5 }, { "grade" : "B", "score" : 23 }] } ...
要了解有关 embeddedDocument 操作符的更多信息,请参阅 embeddedDocument Atlas 指南。
Equals
使用 Equals() 方法检查字段是否与指定值匹配。
以下示例在 movies集合中搜索 year字段的值为 2000 的所有文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Equals(m => m.Year, 2000)) .ToList();
... { "_id" : ObjectId("..."), "title" : "Gladiator", "plot" : "...", "genres" : ["Action", "Adventure", "Drama"], "year" : 2000, "rated" : "R", "imdb" : { "rating" : 8.5, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Cast Away", "plot" : "...", "genres" : ["Adventure", "Drama", "Romance"], "year" : 2000, "rated" : "PG-13", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } } ...
要了解有关 equals 操作符的更多信息,请参阅 equals Atlas 指南。
Exists
使用 Exists() 方法搜索其中存在指定索引字段名称的文档。如果指定的字段存在但未进行索引,则该文档不会包含在结果设立。
以下示例在 movies集合中搜索存在 imdb.rating字段的任何文档。搜索将返回所有包含 imdb.rating字段的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Exists(m => m.Imdb.Rating)) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Godfather", "plot" : "...", "genres" : ["Crime", "Drama"], "year" : 1972, "rated" : "R", "imdb" : { "rating" : 9.2, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "The Shawshank Redemption", "plot" : "...", "genres" : ["Drama"], "year" : 1994, "rated" : "R", "imdb" : { "rating" : 9.3, "votes" : "...", "id" : "..." } } ...
要了解有关 exists 操作符的更多信息,请参阅exists Atlas 指南。
Facet
使用 Facet() 方法按指定分面字段中的值或范围对结果进行分组,并返回每个组的计数。
您可以将 Facet() 方法同时用于 $search 和 $searchMeta 阶段。MongoDB建议使用带有 $searchMeta 阶段的分面(Facet)来检索仅针对查询 的元数据结果。要使用 $search 阶段检索元数据结果和查询结果,必须使用 $$SEARCH_META聚合变量。要学习;了解有关此变量的更多信息,请参阅 SEARCH_META 聚合变量 Atlas指南。
适用以下限制:
只能对单个字段运行分面查询。无法对字段群组运行分面查询。
只能在运行 MongoDB v6.0 的集群上对分片集合运行分面查询。
以下示例在 movies集合中搜索 year字段的值大于或等于 2000 的任何文档。该查询使用 Facet() 方法进程输入文档,根据 genres字段在结果中返回的最大数量 100分面(Facet)面类别。此查询返回找到的不同类型类别的数量:
var result = moviesCollection.Aggregate() .SearchMeta( Builders<Movie>.Search.Facet( Builders<Movie>.Search.Range(m => m.Year, SearchRangeBuilder.Gte(2000)), Builders<Movie>.SearchFacet.String("genres", m => m.Genres, 100)), indexName: "moviesfacetsearch") .Single() .Facet["genres"].Buckets.Count();
23
如要了解有关 facet 收集器的更多信息,请参阅分面 Atlas 指南。
GeoShape
使用 GeoShape() 方法搜索与给定的几何图形相关的文档。当指定要搜索的坐标时,必须首先指定经度,然后指定纬度。经度值可以介于 -180 到 180(含)之间。纬度值可以介于 -90 到 90(含)之间。
注意
MongoDB Search 不支持以下内容:
非默认坐标参考系 (CRS)
平面 XY 坐标系(二维)
坐标对 点符号 (pointFieldName: [12, 34])
此示例使用 sample_mflix数据库中的 theaters集合。以下类对该集合中的文档进行建模:
[] public class Theater { [] public ObjectId Id { get; set; } public int TheaterId { get; set; } public TheaterLocation Location { get; set; } = null!; }
[] public class TheaterLocation { [] public GeoJsonPoint<GeoJson2DGeographicCoordinates> Geo { get; set; } = null!; }
以下示例会在该集合中搜索 location.geo字段中的坐标与明尼苏达州明尼阿波利斯地区的指定多边形相交的所有文档:
GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[] { new(-93.5, 44.7), new(-93.5, 45.0), new(-93.0, 45.0), new(-93.0, 44.7), new(-93.5, 44.7), }))); var result = theatersCollection.Aggregate() .Search(Builders<Theater>.Search.GeoShape( t => t.Location.Geo, GeoShapeRelation.Intersects, searchArea), indexName: "theatersgeo") .ToList();
... { "_id" : ObjectId("..."), "theaterId" : 1000, "location" : { "geo" : { "type" : "Point", "coordinates" : [-93.24565, 44.85466] } } } ...
要了解有关 geoShape 操作符的更多信息,请参阅 geoShape Atlas 指南。
GeoWithin
使用 GeoWithin() 方法搜索指定 GeoJSON 字段坐标在给定几何范围内的文档。您可以搜索以下范围内的点:
圆形
边界框
多边形
指定要搜索的坐标时,必须首先指定经度,然后指定纬度。经度值可以介于 -180 到 180 (含)之间。纬度值可以介于 -90 到 90(含)之间。
注意
MongoDB Search 不支持以下内容:
非默认坐标参考系 (CRS)
平面 XY 坐标系(二维)
坐标对 点符号 (pointFieldName: [12, 34])
以下示例在 theaters集合搜索 location.geo字段中的坐标位于指定多边形内的所有文档:
GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[] { new(-94.0, 44.5), new(-94.0, 45.2), new(-92.5, 45.2), new(-92.5, 44.5), new(-94.0, 44.5), }))); var result = theatersCollection.Aggregate() .Search(Builders<Theater>.Search.GeoWithin(t => t.Location.Geo, searchArea), indexName: "theatersgeo") .ToList();
... { "_id" : ObjectId("..."), "theaterId" : 1000, "location" : { "geo" : { "type" : "Point", "coordinates" : [-93.24565, 44.85466] } } } ...
要了解有关 geoWithin 操作符的更多信息,请参阅 geoWithin Atlas 指南。
登录
使用 In() 方法搜索字段值与指定值列表匹配的文档。
以下示例在 movies集合中搜索具有包含 "Action" 或 "Comedy" 的 genres数组的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.In(m => m.Genres, new[] { "Action", "Comedy" })) .ToList();
... { "_id" : ObjectId("..."), "title" : "Home Alone", "plot" : "...", "genres" : ["Comedy", "Family"], "year" : 1990, "rated" : "PG", "imdb" : { "rating" : 7.4, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Die Hard", "plot" : "...", "genres" : ["Action", "Thriller"], "year" : 1988, "rated" : "R", "imdb" : { "rating" : 8.2, "votes" : "...", "id" : "..." } } ...
更多类似内容
使用 MoreLikeThis() 方法搜索与输入文档类似的文档。
此示例使用以下类来指定用于搜索的输入文档:
public class MovieSearch { public string Plot { get; set; } = null!; }
以下示例在 movies集合搜索与某个对象类似的文档,其中 plot字段的值为 "time travel":
var searchDocument = new MovieSearch() { Plot = "time travel", }; var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.MoreLikeThis(searchDocument)) .ToList();
... { "_id" : ObjectId("..."), "title" : "Thrill Seekers", "plot" : "...", "genres" : ["Action", "Sci-Fi", "Thriller"], "year" : 1999, "rated" : "...", "imdb" : { "rating" : "...", "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "About Time", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2013, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } } ...
要了解有关 moreLikeThis 操作符的更多信息,请参阅 moreLikeThis Atlas 指南。
Near
使用 Near() 方法搜索指定的字段接近给定值的文档。您可以对以下对象执行搜索:
数字字段
日期字段
地理点
以下示例在 movies集合中搜索 imdb.rating字段的值接近 8.5 的文档。根据该值与 8.5 的接近程度按顺序返回文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Near(m => m.Imdb.Rating, 8.5, 1)) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "The Godfather", "plot" : "...", "genres" : ["Crime", "Drama"], "year" : 1972, "rated" : "R", "imdb" : { "rating" : 9.2, "votes" : "...", "id" : "..." } } ...
要了解有关 near 操作符的更多信息,请参阅 near Atlas 指南。
短语
使用 Phrase() 方法搜索指定字段包含输入字符串的文档。
以下示例在 movies集合中搜索 plot字段包含短语 "time travel" 的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Phrase(m => m.Plot, "time travel")) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Safety Not Guaranteed", "plot" : "...", "genres" : ["Comedy", "Drama", "Romance"], "year" : 2012, "rated" : "R", "imdb" : { "rating" : 7, "votes" : "...", "id" : "..." } } ...
您还可以在集合搜索在 plot字段中包含 "time travel" 或 "space adventure" 的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Phrase(m => m.Plot, new List<string>() { "time travel", "space adventure" })) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Safety Not Guaranteed", "plot" : "...", "genres" : ["Comedy", "Drama", "Romance"], "year" : 2012, "rated" : "R", "imdb" : { "rating" : 7, "votes" : "...", "id" : "..." } } ...
要了解有关 phrase 操作符的更多信息,请参阅短语 Atlas 指南。
QueryString
使用 QueryString() 方法,将一个字符串与以下操作符和分隔符结合使用以搜索文档:
ANDORNOT()
以下示例会在 movies 集合中搜索 plot 字段的值与以下每个条件匹配的文档:
包含字符串
"time"或字符串"space"不包含 string
"comedy"
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.QueryString(m => m.Plot, "(time OR space) AND NOT comedy")) .ToList();
... { "_id" : ObjectId("..."), "title" : "Interstellar", "plot" : "...", "genres" : ["Adventure", "Drama", "Sci-Fi"], "year" : 2014, "rated" : "PG-13", "imdb" : { "rating" : 8.7, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Tomorrowland", "plot" : "...", "genres" : ["Action", "Adventure", "Family"], "year" : 2015, "rated" : "PG", "imdb" : { "rating" : 6.6, "votes" : "...", "id" : "..." } } ...
要了解有关 queryString 操作符的更多信息,请参阅 queryString Atlas 指南。
范围
使用 Range() 方法搜索指定字段的值处于给定数字、日期或字符串范围内的文档。
以下示例在 movies集合中搜索 year 值大于 2000 且小于 2010 的所有文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search .Range(m => m.Year, SearchRangeBuilder.Gt(2000).Lt(2010))) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "The Departed", "plot" : "...", "genres" : ["Crime", "Drama", "Thriller"], "year" : 2006, "rated" : "R", "imdb" : { "rating" : 8.5, "votes" : "...", "id" : "..." } } ...
要搜索指定字段的值在某一字符串范围内的文档,必须首先在该字段上创建词索引。创建索引后,您可以根据范围字符串搜索文档。以下示例返回 title字段值介于 "A" 和 "G" 之间的文档(按字典顺序进行比较):
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search .Range(m => m.Title, SearchRangeV2Builder.Gte("A").Lte("G"))) .ToList();
... { "_id" : ObjectId("..."), "title" : "Apollo 13", "plot" : "...", "genres" : ["Adventure", "Drama", "History"], "year" : 1995, "rated" : "PG", "imdb" : { "rating" : 7.6, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Braveheart", "plot" : "...", "genres" : ["Biography", "Drama", "History"], "year" : 1995, "rated" : "R", "imdb" : { "rating" : 8.3, "votes" : "...", "id" : "..." } } ...
要了解有关 range 操作符的更多信息,请参阅 range Atlas 指南。
正则表达式(Regex)
使用 Regex() 方法使用正则表达式搜索文档。
以下示例在 movies集合中搜索 title字段的值恰好包含六个字母的文档:
var regex = "[A-Za-z]{6}"; var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Regex(m => m.Title, regex, allowAnalyzedField: true)) .ToList();
... { "_id" : ObjectId("..."), "title" : "Gandhi", "plot" : "...", "genres" : ["Biography", "Drama", "History"], "year" : 1982, "rated" : "PG", "imdb" : { "rating" : 8.0, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "Batman", "plot" : "...", "genres" : ["Action", "Adventure"], "year" : 1989, "rated" : "PG-13", "imdb" : { "rating" : 7.5, "votes" : "...", "id" : "..." } } ...
注意
在分析字段上运行 Regex
默认下,regex操作符不能在分析字段上运行。您可以通过将 allowAnalyzedField 选项设置为 true,允许其在分析字段上运行,如下所示:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Regex(m => m.Title, regex, allowAnalyzedField: true)) .ToList();
将 allowAnalyzedField 选项设置为 true 可能会导致意外的搜索结果。要学习;了解详情,请参阅行为Atlas regex指南中的。
要了解有关 regex 操作符的更多信息,请参阅 regex Atlas 指南。
span
使用 Span() 方法,搜索字段区域内的文本搜索匹配项。您可以使用该方法,按照指定的精度查找相似的字符串。
注意
Span 操作符性能
span 操作符比其他操作符的计算量更大,因为查询必须跟踪位置信息。
以下示例在 movies集合中搜索 plot字段的值包含字符串 "time" 和 "travel" 且彼此相邻的单词的文档:
var searchTerms = new[] { Builders<Movie>.SearchSpan.Term(m => m.Plot, "time"), Builders<Movie>.SearchSpan.Term(m => m.Plot, "travel") }; var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Span(Builders<Movie>.SearchSpan.Near(searchTerms, 1))) .ToList();
... { "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "About Time", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2013, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } } ...
要了解有关 span 操作员的更多信息,请参阅 span Atlas 指南。
Text
使用 Text() 方法在文档中搜索给定的 string 或字符串数组。如果给定字符串中有多个词, MongoDB Search 还会分别为字符串中的每个术语查找匹配项。
以下示例在 movies集合中搜索 plot字段的值包含 string "secret agent" 的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Text(m => m.Plot, "secret agent")) .ToList();
... { "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "genres" : ["Action", "Adventure", "Comedy"], "year" : 2001, "rated" : "PG", "imdb" : { "rating" : 5.4, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "genres" : ["Action", "Adventure", "Thriller"], "year" : 1977, "rated" : "PG", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } } ...
提示
多术语搜索行为
如果您的搜索字符串包含多个术语,此方法还会分别查找字符串中的每个术语的匹配项。
要了解有关 text 操作符的更多信息,请参阅 text Atlas 指南。
通配符
使用 Wildcard() 方法在搜索字符串中使用可以匹配任何字符的特殊字符来搜索文档。您可以在搜索中使用以下字符:
字符 | 说明 |
|---|---|
| 匹配任意单个字符。 |
| 匹配 0 个或更多字符。 |
| 转义字符 |
以下示例搜索 title字段的值包含 string "Amer",后跟任何其他字符的文档:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Wildcard(m => m.Title, "Amer*", allowAnalyzedField: true)) .ToList();
... { "_id" : ObjectId("..."), "title" : "American Beauty", "plot" : "...", "genres" : ["Drama"], "year" : 1999, "rated" : "R", "imdb" : { "rating" : 8.4, "votes" : "...", "id" : "..." } } { "_id" : ObjectId("..."), "title" : "American Gangster", "plot" : "...", "genres" : ["Biography", "Crime", "Drama"], "year" : 2007, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } } ...
注意
在分析字段上运行通配符
默认下,wildcard操作符不能在分析字段上运行。您可以通过将 allowAnalyzedField 选项设置为 true,以允许其在已分析字段上运行,如下所示:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Wildcard(m => m.Title, "Amer*", allowAnalyzedField: true)) .ToList();
将 allowAnalyzedField 选项设置为 true,可能会导致意外的搜索结果。要了了解详情,请参阅 wildcard 行为。
要了解有关 wildcard 操作符的更多信息,请参阅 wildcard Atlas 指南。
Specify a Search Path
You can specify the path to the field or fields to search by using the SearchPathDefinitionBuilder class. Use Builders<TDocument>.SearchPath to access a SearchPathDefinitionBuilder instance and call one of its methods to specify the search path. The following sections describe the available methods.
提示
Search Paths
To learn more about search paths, see Construct a Query Path in the Atlas documentation.
单个字段
Use the Single() method to specify one field as the search path. The following examples show three ways to specify the field: by using a lambda expression with a typed model, by passing a string field name such as a fieldName variable or method parameter whose value is known at runtime, or by using an untyped document.
注意
The field that you pass to the Single() method must be included in the search index definition. If the field isn't included, MongoDB Server returns an empty result set without returning an error.
Lambda Expression
Use a lambda expression when you're working with a typed model and you know the field name at compile time. This form provides compile-time type checking.
The following example searches the plot field for documents that contain the text "secret agent":
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Text( Builders<Movie>.SearchPath.Single(m => m.Plot), "secret agent")) .ToList();
[ "...", { "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "genres" : ["Action", "Adventure", "Comedy"], "year" : 2001, "rated" : "PG", "imdb" : { "rating" : 5.4, "votes" : "...", "id" : "..." } }, "...", { "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "genres" : ["Action", "Adventure", "Thriller"], "year" : 1977, "rated" : "PG", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }, "..." ]
String Field Name
Use a FieldDefinition<TDocument> when you're working with a typed model but you don't know the field name at compile time. Consider using this form if you're retrieving the field name from user input or a configuration file.
The following example assigns the field name to a FieldDefinition<Movie> variable and passes it to Single():
FieldDefinition<Movie> runtimeField = fieldName; var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Text( Builders<Movie>.SearchPath.Single(runtimeField), "secret agent")) .ToList();
[ "...", { "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "genres" : ["Action", "Adventure", "Comedy"], "year" : 2001, "rated" : "PG", "imdb" : { "rating" : 5.4, "votes" : "...", "id" : "..." } }, "...", { "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "genres" : ["Action", "Adventure", "Thriller"], "year" : 1977, "rated" : "PG", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }, "..." ]
BsonDocument
You must also specify the field name as a string when you're working with BsonDocument objects instead of a typed model.
The following example searches an untyped collection for documents in the plot field that contain the text "secret agent":
var result = moviesCollectionBson.Aggregate() .Search(Builders<BsonDocument>.Search.Text( Builders<BsonDocument>.SearchPath.Single("plot"), "secret agent")) .ToList();
[ "...", { "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "...": "..." }, "...", { "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "...": "..." }, "..." ]
多个字段
Use the Multi() method to specify the search path for multiple fields. The result set includes documents that match on any of the specified fields.
注意
You must include all fields that you pass to the Multi() method in the search index definition. If you pass a field that isn't included, MongoDB Server silently excludes it from the search.
以下示例在 plot 或 title字段中搜索短语 "time travel":
var result = moviesCollection.Aggregate().Search( Builders<Movie>.Search.Phrase(Builders<Movie>.SearchPath .Multi(m => m.Plot, m => m.Title), "time travel"), indexName: "moviesmulti") .ToList();
[ "...", { "title" : "Safety Not Guaranteed", "year" : 2012, "rated" : "R" }, { "title" : "The Time Traveler's Wife", "year" : 2009, "rated" : "PG-13" }, "..." ]
分析器
Analyzers process text into searchable tokens by applying operations such as lowercasing. MongoDB Server applies an analyzer when indexing a field and again when running a query against that field. If you specify the multi option when you create a search index, MongoDB Server also stores a second set of tokens produced by an alternate analyzer.
You can use the Analyzer() method to run a query against the tokens produced by a multi analyzer instead of the tokens produced by the field's default analyzer. The name you pass to Analyzer() must be the key name of the multi block in your index definition, not the name of the underlying analyzer.
The following example uses a multi analyzer named "lucene" to search the title field for documents that contain the text "gravity":
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Text( Builders<Movie>.SearchPath.Analyzer(m => m.Title, "lucene"), "gravity"), indexName: "moviesanalyzer") .ToList();
[ "...", { "title" : "Gravity", "year" : 2013, "rated" : "PG-13" }, "..." ]
Wildcard Path
Use the Wildcard() method to specify a search path that uses wildcard characters to match field names. You can use the * character in the field name to match any sequence of characters.
MongoDB Server searches only fields that meet the following conditions:
The field must be indexed.
The field name must match the specified pattern.
The field's data type must match the search operator. For example, a
Text()query searches only string fields.
The following example searches all fields whose names start with "p" for documents that contain the text "secret agent":
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Text( Builders<Movie>.SearchPath.Wildcard("p*"), "secret agent")) .ToList();
[ "...", { "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "genres" : ["Action", "Adventure", "Comedy"], "year" : 2001, "rated" : "PG", "imdb" : { "rating" : 5.4, "votes" : "...", "id" : "..." } }, "...", { "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "genres" : ["Action", "Adventure", "Thriller"], "year" : 1977, "rated" : "PG", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }, "..." ]
注意
Wildcard Performance
Broad patterns, such as "*", match all indexed fields and might affect query performance on large indexes.
To learn more about wildcard paths, see Construct a Query Path in the Atlas documentation.
对文档进行评分
MongoDB Server会为其从MongoDB搜索查询中返回的每个文档分配一个相关性分数。查询按从最高分到最低分的顺序返回文档。要学习;了解有关如何分配分数的更多信息,请参阅分数Atlas指南。
分配给返回文档的分数是文档元数据的一部分。您可以通过在聚合管道中使用 $project 阶段,将每个返回文档的分数与结果设立一起包含在内。
以下示例在 movies集合中搜索 title字段的值恰好包含六个字母的文档,并使用 $project 阶段将名为 score 的字段添加到返回的文档:
var regex = "[A-Za-z]{6}"; var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Regex(m => m.Title, regex, allowAnalyzedField: true), indexName: "moviescore") .Project<Movie>(Builders<Movie>.Projection .Include(m => m.Id) .Include(m => m.Title) .Include(m => m.Plot) .MetaSearchScore(m => m.Score)) .ToList();
... { "_id" : ObjectId("..."), "title" : "Gandhi", "plot" : "...", "score" : 1.0 } { "_id" : ObjectId("..."), "title" : "Batman", "plot" : "...", "score" : 1.0 } ...
修改MongoDB搜索行为
您可以通过传递 SearchOptions对象作为参数来修改 Search() 方法的行为。
SearchOptions 类包含以下属性:
属性 | 说明 |
|---|---|
| The options for counting the search results. Data type: SearchCountOptions Default: null |
| The options for displaying search terms in their original context. Data type: SearchHighlightOptions<TDocument> Default: null |
| The index to use for the search. Data type: stringDefault: null |
| A flag that specifies whether to perform a full document lookup on
the database or to return only stored source fields directly from
MongoDB Search. Data type: booleanDefault: false |
| A flag that specifies whether to return detailed information about the
score for each document in the results. Data type: booleanDefault: false |
| The starting point for pagination. When set, the search retrieves documents
starting immediately after the specified reference point. Data type: stringDefault: null |
| The end point for pagination. When set, the search retrieves documents
starting immediately before the specified reference point. Data type: stringDefault: null |
| The sorting criteria to apply to the results. Data type: SortDefinition<TDocument> Default: null |
| The options for tracking search terms. Data type: SearchTrackingOptions Default: null |
SearchAfter 示例
以下示例通过执行以下操作对MongoDB搜索操作的结果进行分页:
定义使用
MetaSearchSequenceToken()构建器方法的投影,该方法指定一个PaginationToken来包含参考点创建
SearchOptions实例,并设置要使用的索引和排序条件运行初始搜索以查找具有
plot字段值且包含文本"time travel"的文档,并将投影和选项应用于操作将同一
SearchOptions实例的SearchAfter属性设置为指示下一个搜索在基本搜索的第一个结果之后开始运行具有相同匹配条件的另一个搜索操作,并应用搜索选项对结果进行分页
var projection = Builders<Movie>.Projection .Include(x => x.Title) .MetaSearchSequenceToken(x => x.PaginationToken); var searchDefinition = Builders<Movie>.Search.Text(m => m.Plot, "time travel"); var searchOptions = new SearchOptions<Movie> { IndexName = "default", Sort = Builders<Movie>.Sort.Ascending(m => m.Id) }; // Runs the base search operation var baseSearchResults = moviesCollection.Aggregate() .Search(searchDefinition, searchOptions) .Project<Movie>(projection) .ToList(); if (baseSearchResults.Count == 0) return baseSearchResults; // Sets the starting point for the next search searchOptions.SearchAfter = baseSearchResults[0].PaginationToken; var result = moviesCollection.Aggregate() .Search(searchDefinition, searchOptions) .Project<Movie>(projection) .ToList();
... { "_id" : ObjectId("..."), "title" : "About Time", "plot" : "...", "genres" : ["Comedy", "Drama", "Romance"], "year" : 2013, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } } ...