接近
定义
near
near
操作符支持对数字、日期和字符串值进行查询和评分。此操作符可用于对以下各项执行搜索:BSON
int32
、int64
和double
数据类型的数字字段。BSON
date
类型的日期字段采用 ISODate 格式。使用纬度和经度坐标定义的地理位置字段。
可以使用
near
操作符查找接近一个数字或日期的结果。near
操作符根据与数字或日期的接近程度对 Atlas Search 结果进行评分。
语法
near
通过以下语法实现:
{ $search: { "index": <index name>, // optional, defaults to "default" "near": { "path": "<field-to-search>", "origin": <date-or-number>, "pivot": <pivot-distance>, "score": <score-options> } } }
选项
near
使用以下词条来构造查询:
字段 | 类型 | 说明 | 必要性 | |||
---|---|---|---|---|---|---|
| 日期、数字或地理位置 | 是 | ||||
| 字符串或字符串数组 | 要搜索的一个或多个带索引字段。请参阅路径构造。 | 是 | |||
| 数字 | 用于计算 Atlas Search 结果文档的分数的值。分数使用以下公式计算:
其中, 当结果的索引字段值与 如果
| 是 | |||
| 对象 | 分配给匹配搜索结果的分数。您可以使用以下选项修改默认分数:
有关在查询中使用 | no |
评分行为
Atlas Search score
是 Atlas Search 结果与 origin
的接近度的度量。score
的量值范围为 0
至 1
,其中,1
表示精确匹配,0
表示匹配度很低。当 Atlas Search 结果与 origin
的距离等于使用 pivot
计算的距原点的距离时,分数等于 0.5
。
分数使用以下公式计算:
pivot score = ------------------ pivot + distance
其中,distance
是 origin
与索引字段值之间的差值。
可以在查询中使用 score
选项修改默认分数。要了解有关选项的详细信息,请参阅修改分数。
限制
即使有 Atlas Search 索引,也无法使用 near
操作符查询存储在数组中的数字或日期值。只能使用 range 操作符来查询数组内的索引数字或日期值。
示例
数字和日期示例使用sample_mflix
数据库中的movies
集合。 GeoJSON 点示例使用sample_airbnb
数据库中的listingsAndReviews
集合。
如果在 Atlas 集群上加载示例数据,则可以使用以下示例中的索引定义或动态索引来创建静态索引,并在集群上运行示例查询。
提示
如果您已经加载示例数据集,请按照 Atlas Search 入门教程,创建索引定义并运行 Atlas Search 查询。
数字示例
以下示例使用 near
操作符查询数字字段。
例子
以下名为 runtimes
的索引定义对 movies
集合中的 runtime
字段值编制索引:
1 { 2 "mappings": { 3 "dynamic": false, 4 "fields": { 5 "runtime": { 6 "type": "number" 7 } 8 } 9 } 10 }
以下查询在movies
集合中搜索runtime
字段值接近279的文档。 它包括一个用于将输出限制为7个结果的$limit
阶段和一个用于执行以下操作的$project
阶段:
排除
title
和runtime
之外的所有字段添加字段
score
score
是使用 pivot
计算得出。
1 db.movies.aggregate([ 2 { 3 $search: { 4 "index": "runtimes", 5 "near": { 6 "path": "runtime", 7 "origin": 279, 8 "pivot": 2 9 } 10 } 11 }, 12 { 13 $limit: 7 14 }, 15 { 16 $project: { 17 "_id": 0, 18 "title": 1, 19 "runtime": 1, 20 score: { $meta: "searchScore" } 21 } 22 } 23 ])
以上查询返回以下结果:
1 { "runtime" : 279, "title" : "The Kingdom", "score" : 1 } 2 { "runtime" : 279, "title" : "The Jinx: The Life and Deaths of Robert Durst", "score" : 1 } 3 { "runtime" : 280, "title" : "Shoah", "score" : 0.6666666865348816 } 4 { "runtime" : 281, "title" : "Les Misèrables", "score" : 0.5 } 5 { "runtime" : 277, "title" : "Tokyo Trial", "score" : 0.5 } 6 { "runtime" : 276, "title" : "Warriors of the Rainbow: Seediq Bale", "score" : 0.4000000059604645 } 7 { "runtime" : 283, "title" : "Scenes from a Marriage", "score" : 0.3333333432674408 }
在上面的 Atlas Search 结果中,电影 The Kingdom
和 The
Jinx: The Life and Deaths of Robert Durst
的分数为 1.0
,因为它们的 runtime
字段值 279
是完全匹配的。电影 Les Misèrables
和 Tokyo Trial
的分数为 0.5
,因为它们的 runtime
字段值与 279
相差 2
个单位。
日期示例
以下示例使用 near
操作符查询日期字段。
例子
以下名为 releaseddate
的索引定义对 movies
集合中的 released
字段值编制索引:
1 { 2 "mappings": { 3 "dynamic": false, 4 "fields": { 5 "released": { 6 "type": "date" 7 } 8 } 9 } 10 }
以下查询搜索 9 月13 、 1前后上映的电影。 它包括一个用于将输出限制为3
结果的$limit
阶段和一个用于执行以下操作的$project
阶段:
排除
title
和released
之外的所有字段添加字段
score
结果的 score
将使用 pivot
计算得出。
注意
pivot
此处以毫秒为单位,7,776,000,000 ms
等于大约三个月。
1 db.movies.aggregate([ 2 { 3 $search: { 4 "index": "releaseddate", 5 "near": { 6 "path": "released", 7 "origin": ISODate("1915-09-13T00:00:00.000+00:00"), 8 "pivot": 7776000000 9 } 10 } 11 }, 12 { 13 $limit: 3 14 }, 15 { 16 $project: { 17 "_id": 0, 18 "title": 1, 19 "released": 1, 20 score: { $meta: "searchScore" } 21 } 22 } 23 ])
以上查询会返回以下搜索结果:
{ "title" : "Regeneration", "released" : ISODate("1915-09-13T00:00:00Z"), "score" : 1 } { "title" : "The Cheat", "released" : ISODate("1915-12-13T00:00:00Z"), "score" : 0.49723756313323975 } { "title" : "Hell's Hinges", "released" : ISODate("1916-03-05T00:00:00Z"), "score" : 0.34090909361839294 }
在上面的 Atlas Search 结果中,电影 Regeneration
的分数为 1
,因为 1915-09-13
的 released
字段值是精确匹配项。在 1915-12-13
上映的电影 The Cheat
的分数约为 0.5
,因为 1915-09-13
的 released
字段值与 origin
相差约 7,776,000,000
毫秒。
GeoJSON 点示例
以下示例使用 near
操作符查询 sample_airbnb.listingsAndReviews
集合中的 GeoJSON 点对象。以下索引定义对 listingsAndReviews
集合中的 address.location
和 property_type
字段编制索引。
例子
1 { 2 "mappings": { 3 "fields": { 4 "address": { 5 "fields": { 6 "location": { 7 "type": "geo" 8 } 9 }, 10 "type": "document" 11 }, 12 "property_type": { 13 "type": "string" 14 } 15 } 16 } 17 }
基本示例
以下示例使用 near
操作符查询 sample_airbnb.listingsAndReviews
集合中的 address.location
字段。
例子
以下查询将搜索葡萄牙的房产。其中包含一个 $limit
阶段,用于将输出限制为 3
个结果,并包含一个 $project 阶段,用于:
排除
name
和address
之外的所有字段添加字段
score
结果的 score
将使用 pivot
计算得出。请注意,此处测量的 pivot
的单位为米,1000 米等于 1 公里。
1 db.listingsAndReviews.aggregate([ 2 { 3 "$search": { 4 "near": { 5 "origin": { 6 "type": "Point", 7 "coordinates": [-8.61308, 41.1413] 8 }, 9 "pivot": 1000, 10 "path": "address.location" 11 } 12 } 13 }, 14 { 15 $limit: 3 16 }, 17 { 18 $project: { 19 "_id": 0, 20 "name": 1, 21 "address": 1, 22 score: { $meta: "searchScore" } 23 } 24 } 25 ])
以上查询会返回以下搜索结果:
1 { 2 "name" : "Ribeira Charming Duplex", 3 "address" : { 4 "street" : "Porto, Porto, Portugal", 5 "suburb" : "", 6 "government_area" : "Cedofeita, Ildefonso, Sé, Miragaia, Nicolau, Vitória", 7 "market" : "Porto", 8 "country" : "Portugal", 9 "country_code" : "PT", 10 "location" : { 11 "type" : "Point", 12 "coordinates" : [ -8.61308, 41.1413 ], 13 "is_location_exact" : false 14 } 15 }, 16 "score" : 1 17 } 18 { 19 "name" : "DB RIBEIRA - Grey Apartment", 20 "address" : { 21 "street" : "Porto, Porto, Portugal", 22 "suburb" : "", 23 "government_area" : "Cedofeita, Ildefonso, Sé, Miragaia, Nicolau, Vitória", 24 "market" : "Porto", 25 "country" : "Portugal", 26 "country_code" : "PT", 27 "location" : { 28 "type" : "Point", 29 "coordinates" : [ -8.61294, 41.14126 ], 30 "is_location_exact" : true 31 } 32 }, 33 "score" : 0.9876177310943604 34 } 35 { 36 "name" : "Ribeira 24 (4)", 37 "address" : { 38 "street" : "Porto, Porto, Portugal", 39 "suburb" : "", 40 "government_area" : "Cedofeita, Ildefonso, Sé, Miragaia, Nicolau, Vitória", 41 "market" : "Porto", 42 "country" : "Portugal", 43 "country_code" : "PT", 44 "location" : { 45 "type" : "Point", 46 "coordinates" : [ -8.61318, 41.14107 ], 47 "is_location_exact" : false 48 } 49 }, 50 "score" : 0.973789632320404 51 }
结果显示,距离指定坐标较远的属性的得分较低。
复合示例
以下示例使用 compound
操作符查询 sample_airbnb.listingsAndReviews
集合中的 property_type
和 address.location
字段。
例子
以下查询搜索指定 GeoJSON 点附近的香港公寓。 查询使用“必须”指定必须满足的Atlas Search条件,并使用“ should ”指定位置偏好。 它包括一个用于将输出限制为3结果的$limit
阶段和一个用于执行以下操作的$project阶段:
排除
property_type
和address
之外的所有字段添加字段
score
score
是使用 pivot
字段计算得出。请注意,此处测量的 pivot
的单位为米,1000 米等于 1 公里。
1 db.listingsAndReviews.aggregate([ 2 { 3 $search: { 4 "compound": { 5 "must": { 6 "text": { 7 "query": "Apartment", 8 "path": "property_type" 9 } 10 }, 11 "should": { 12 "near": { 13 "origin": { 14 "type": "Point", 15 "coordinates": [114.15027, 22.28158] 16 }, 17 "pivot": 1000, 18 "path": "address.location" 19 } 20 } 21 } 22 } 23 }, 24 { 25 $limit: 3 26 }, 27 { 28 $project: { 29 "_id": 0, 30 "property_type": 1, 31 "address": 1, 32 score: { $meta: "searchScore" } 33 } 34 } 35 ])
以上查询会返回以下搜索结果:
1 { 2 "property_type" : "Apartment", 3 "address" : { 4 "street" : "Hong Kong, Hong Kong Island, Hong Kong", 5 "suburb" : "Central & Western District", 6 "government_area" : "Central & Western", 7 "market" : "Hong Kong", 8 "country" : "Hong Kong", 9 "country_code" : "HK", 10 "location" : { 11 "type" : "Point", 12 "coordinates" : [ 114.15027, 22.28158 ], 13 "is_location_exact" : true 14 } 15 }, 16 "score" : 1.177286982536316 17 } 18 { 19 "property_type" : "Apartment", 20 "address" : { 21 "street" : "Hong Kong, Hong Kong Island, Hong Kong", 22 "suburb" : "Central & Western District", 23 "government_area" : "Central & Western", 24 "market" : "Hong Kong", 25 "country" : "Hong Kong", 26 "country_code" : "HK", 27 "location" : { 28 "type" : "Point", 29 "coordinates" : [ 114.15082, 22.28161 ], 30 "is_location_exact" : true 31 } 32 }, 33 "score" : 1.1236450672149658 34 } 35 { 36 "property_type" : "Apartment", 37 "address" : { 38 "street" : "Hong Kong, 39 Hong Kong Island, Hong Kong", 40 "suburb" : "Mid-Levels", 41 "government_area" : "Central & Western", 42 "market" : "Hong Kong", 43 "country" : "Hong Kong", 44 "country_code" : "HK", 45 "location" : { 46 "type" : "Point", 47 "coordinates" : [ 114.15007, 22.28215 ], 48 "is_location_exact" : true 49 } 50 }, 51 "score" : 1.114811897277832 52 }