Đầu tiên, tôi thực sự khuyên bạn nên tạo chỉ mục "2dsphere" cho bộ sưu tập của mình nếu bạn có ý định truy vấn không gian địa lý về tọa độ trong thế giới thực.
Đảm bảo bỏ các chỉ mục khác mà bạn có thể đã chơi:
db.records.dropIndexes();
db.records.createIndex({ "addresses.loc": "2dsphere" })
Để thực hiện những gì bạn muốn, trước tiên hãy xem bản sửa đổi nhỏ cũng bao gồm includeLocs tùy chọn $geoNear
db.records.aggregate([
{ "$geoNear": {
"near": [ -73.9815103, 40.7475731 ],
"spherical": true,
"distanceField": "distance",
"includeLocs": "locs"
}}
])
Bây giờ bạn sẽ thấy đầu ra giống như sau:
{
"_id" : ObjectId("592d0c78555a7436b0883960"),
"userid" : 7,
"addresses" : [
{
"apporx" : 50,
"loc" : [
-73.98137109999999,
40.7476039
]
},
{
"apporx" : 15,
"loc" : [
-73.982002,
40.74767
]
},
{
"apporx" : 10,
"loc" : [
-73.9819567,
40.7471609
]
}
],
"distance" : 0.0000019174641401278624,
"locs" : [
-73.98137109999999,
40.7476039
]
}
Vì vậy, những gì trả về không chỉ là khoảng cách đến điểm gần nhất mà là "vị trí" mà trận đấu đã sử dụng.
Vì vậy, nếu bạn muốn $filter
mảng ban đầu để trả về mảng gần nhất, sau đó bạn có thể:
db.records.aggregate([
{ "$geoNear": {
"near": [ -73.9815103, 40.7475731 ],
"spherical": true,
"distanceField": "distance",
"includeLocs": "locs"
}},
{ "$addFields": {
"addresses": {
"$filter": {
"input": "$addresses",
"as": "address",
"cond": { "$eq": [ "$$address.loc", "$locs" ] }
}
}
}}
])
Và điều đó trả về mảng chỉ có phù hợp đó:
{
"_id" : ObjectId("592d0c78555a7436b0883960"),
"userid" : 7,
"addresses" : [
{
"apporx" : 50,
"loc" : [
-73.98137109999999,
40.7476039
]
}
],
"distance" : 0.0000019174641401278624,
"locs" : [
-73.98137109999999,
40.7476039
]
}