near 操作符限制
即使有MongoDB Search索引,也无法使用 near操作符查询存储在大量中的数字或日期值。您只能使用 范围来查询数组内的索引数字或日期值。
定义
nearnear操作符支持对数字、日期和字符串值进行查询和评分。此操作符可用于对以下各项执行搜索:BSON
int32、int64和double数据类型的数字字段。BSON
date类型的日期字段采用 ISODate 格式。使用纬度和经度坐标定义的地理位置字段。
您可以使用
near操作符查找接近数字或日期的结果。near操作符根据与数字或日期的接近程度对MongoDB搜索结果进行评分。
语法
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 使用以下词条来构造查询:
字段 | 类型 | 说明 | 必要性 | |||
|---|---|---|---|---|---|---|
| 日期、数字或地理位置 | 要在附近搜索的数字、日期或地理位置点。这是测量结果接近度的起点。
| 是 | |||
| 字符串或字符串数组 | 要搜索的一个或多个带索引字段。 | 是 | |||
| 数字 | 用于计算MongoDB搜索结果文档分数的值。分数使用以下公式计算: 其中, 当结果的索引字段值与 如果
| 是 | |||
| 对象 | 分配给匹配搜索结果的分数。您可以使用以下选项修改默认分数:
有关在查询中使用 | no |
评分行为
MongoDB Search score 是MongoDB Search 结果与 origin 的接近程度的度量。score 在 0 和 1 之间调整,其中 1 为精确匹配,0 为远程匹配。当MongoDB搜索结果与 origin 的距离等于使用 pivot 计算的距原点的距离时,分数等于 0.5。
near 操作符使用以下距离衰减函数来计算文档得分:
pivot score = ------------------ pivot + distance
其中每个术语的定义如下:
因子 | 说明 | |
|---|---|---|
| 指定为参考点的值,如果 | |
|
其中:
|
可以在查询中使用 score 选项修改默认分数。要了解有关选项的详细信息,请参阅修改分数。
示例
数字和日期示例使用sample_mflix数据库中的movies集合。 GeoJSON 点示例使用sample_airbnb数据库中的listingsAndReviews集合。
If you load the sample data on your cluster, you can create the static indexes using the index definitions in the examples below or the dynamic index and run the example queries on your cluster.
提示
If you've already loaded the sample dataset, refer to the MongoDB Search Quick Start tutorial to create an index definition and run MongoDB Search queries.
数字示例
以下示例使用 near 操作符查询数字字段。以下查询使用名为 runtimes 的索引,该索引动态地为 movies 集合中的所有字段创建索引。该查询在 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": "year", 7 "origin": 2000, 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 ])
[ { runtime: 279, title: 'The Kingdom', score: 1 }, { runtime: 279, title: 'The Kingdom', score: 1 }, { runtime: 279, title: 'The Jinx: The Life and Deaths of Robert Durst', score: 1 }, { runtime: 281, title: 'Les Misèrables', score: 0.5 }, { runtime: 277, title: 'Tokyo Trial', score: 0.5 }, { runtime: 283, title: 'Scenes from a Marriage', score: 0.3333333432674408 }, { runtime: 274, title: 'The Crimson Petal and the White', score: 0.2857142984867096 } ]
在MongoDB搜索结果中,电影 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 个单位。
元数据示例
以下查询返回搜索条件的元数据结果。也就是说,它使用 $searchMeta 阶段来获取以下存储桶(年份)中符合搜索条件的电影数量:
2000,包括此存储桶的下限
2005,2000 存储桶的不含上限以及此存储桶的包含下限
2010,2005 存储桶的不含上限以及此存储桶的包含下限
2010,2010 存储桶的独占上限
1 db.movies.aggregate([ 2 { 3 "$searchMeta": { 4 "facet": { 5 "operator": { 6 "near": { 7 "path": "runtime", 8 "origin": 279, 9 "pivot": 2 10 } 11 }, 12 "facets": { 13 "yearFacet": { 14 "type": "number", 15 "path": "year", 16 "boundaries": [2000, 2005, 2010, 2015 ] 17 } 18 } 19 } 20 } 21 } 22 ])
[ { count: { lowerBound: Long('20910') }, facet: { yearFacet: { buckets: [ { _id: 2000, count: Long('3058') }, { _id: 2005, count: Long('4012') }, { _id: 2010, count: Long('4669') } ] } } } ]
日期示例
以下示例使用 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 }
在上面的MongoDB 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 字段。
例子
The following query searches for properties in Portugal. It includes a $limit stage to limit the output to 3 results and a $project stage to:
排除
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 字段。
例子
The following query searches for apartments in Hong Kong near a specified GeoJSON point. The query uses must to specify the search condition, which must be met, and should to specify preference for location. It includes a $limit stage to limit the output to 3 results and a $project stage to:
排除
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 }