Overview
在本指南中,您可以了解如何使用 Search 生成器,通过 MongoDB .NET/C# 驱动程序构建一个聚合管道阶段。
要了解有关 $search 管道阶段的更多信息,请参阅 $search。
注意
仅适用于 Atlas for MongoDB v4.2 及更高版本
$search 聚合管道操作符仅适用于在运行 MongoDB v4.2 或更高版本的 MongoDB Atlas 集群上托管且由 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 SearchScoreDetails ScoreDetails { get; set; } = null!; [] 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提供的示例数据集。请参阅快速入门,学习;了解如何创建免费的MongoDB 集群并加载此示例数据。
创建MongoDB搜索索引
在对Atlas集合执行搜索之前,必须先在该集合上创建Atlas Search索引。MongoDB搜索索引是一种以可搜索格式对数据进行分类的数据结构。
要学习;了解如何创建MongoDB搜索索引,请参阅创建MongoDB搜索索引Atlas指南。
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" : "..." } } ...
注意
自动完成查询的索引
您必须创建支持自动完成的MongoDB搜索索引,才能成功执行自动完成查询。要学习更多信息,请参阅Atlas文档中的如何对字段进行索引以支持自动完成。
创建MongoDB Search索引后,必须将索引名称传递给 Autocomplete() 方法,如前面的示例所示。
要了解有关 autocomplete 操作符的更多信息,请参阅 autocomplete Atlas 指南。
多个子句
使用 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字段的任何文档:
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 指南。
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" : "..." } } ...
要了解有关 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 操作符不能在分析字段上运行。您可以通过将 allowAnalyzedField 选项设置为 true,支持在分析字段上执行该操作符,如下所示:
var result = moviesCollection.Aggregate() .Search(Builders<Movie>.Search.Regex(m => m.Title, regex, allowAnalyzedField: true)) .ToList();
将 allowAnalyzedField 选项设置为 true 可能会导致意外的搜索结果。要了解详情,请参阅 regex 行为。
要了解有关 regex 操作符的更多信息,请参阅 regex Atlas 指南。
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 指南。