问题
I have a collection that looks like that
{
"_class" : "User",
"_id" : "id1",
"places" : [
{
"_id" : "1",
"address" : "test1",
"location" : {
"latitude" : 1,
"longitude" : 1
}
},
{
"_id" : "2",
"address" : "test2",
"location" : {
"latitude" : 2,
"longitude" : 2
}
},...
]
}
I am trying to retrieve every place of a user (in a range of 2 km). This query doesn't work :
db.users.ensureIndex({"places.location":"2d"})
db.users.aggregate([
{$match : { "_id" : "id1" } },
{$unwind : "$places"},
{$project:{_id:0, places:1},
{$match :
{"places.location" :
{ $near :
{ $geometry :
{ type : "2d" ,
coordinates : [ -1 , -2 ]
}
},
$maxDistance : 2000
}
}
}])
Error: Printing Stack Trace
at printStackTrace (src/mongo/shell/utils.js:37:15)
at DBCollection.aggregate (src/mongo/shell/collection.js:897:9)
at (shell):1:10
JavaScript execution failed: aggregate failed: {
"errmsg" : "exception: $near is not allowed inside of a $match aggregation expression",
"code" : 16424,
"ok" : 0
I don't know how to use $near with aggregation.
When i try
db.users.find(
{
"places.location" :
{ $near:
{ $geometry :
{ type : "2d" ,
coordinates : [ -1 , -2 ] }
},
$maxDistance : 2000
}
}
It returns me n times the given user (n = each place of the user), this is why i have decided to use aggregation, but i'm stuck.
Thx in advance
EDIT
I tried $geoNear :
db.users.aggregate(
{$geoNear : {
near: [-1, 1],
distanceField: "distance",
query : {"_id" : "id1"},
uniqueDocs: true,
maxDistance : 2000 // In the specs, distance has to be in radians
}})
and it returns me the whole user (with all the places, even the far ones).
So I need to rework the document before I search for the correct places.
- Retrieve the correct user (match)
- Unwind every places of the user
- then search every place in a range of 2 km (near/geonear)
- reshape the result (project)
The result I am expecting is something like :
"result" : [
{
"_id" : "1",
"location" : {
"latitude" : 1,
"longitude" : 1
}
},
{
"_id" : "2",
"location" : {
"latitude" : 2,
"longitude" : 2
}
}
]}
The problem is that I can't use other stages before $geoNear, my search parameters have to be specified in the "query" field. I get the following error :
$geoNear is only allowed as the first pipeline stage
回答1:
You will have to use $geoNear, and only if you are using V2.4 onward
db.users.aggregate(
{$geoNear : {
near: [-1, -2],
distanceField: "distance",
query : {"_id" : "id1"},
uniqueDocs: true,
maxDistance : 2000
}})
Edit : after edit to question
The bellow query will give you location and distance, but doesn't retrieve the internal (array element) _id
db.users.aggregate(
{$geoNear : {
near: [-1, -2],
distanceField: "distance",
includeLocs: "location",
query : {"_id" : "id1"},
maxDistance : 2000
}},
{$project : {"location" : 1, "_id" : 0, "distance" : 1}}
)
Note the addition of includeLocs
and elimination of uniqueDocs: true
To also retrieve the internal _id, you will have to (following this example) unwind and conditionally project or so, but I don't think it worth it, unless you need the address instead of the _id
来源:https://stackoverflow.com/questions/21650385/mongodb-query-near-with-aggregation