MongoDB查询:$ near with aggregation

时间:2014-02-08 18:55:31

标签: mongodb aggregation-framework

我有一个看起来像那个

的集合
{
    "_class" : "User",
    "_id" : "id1",
    "places" : [
            {
                    "_id" : "1",
                    "address" : "test1",
                    "location" : {
                            "latitude" : 1,
                            "longitude" : 1
                    }
            },
            {
                    "_id" : "2",
                    "address" : "test2",
                    "location" : {
                            "latitude" : 2,
                            "longitude" : 2
                    }
            },...
     ]
}

我正在尝试检索用户的每个地方(范围为2公里)。此查询不起作用:

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

我不知道如何使用$ near with aggregation。

当我尝试

db.users.find(
                  {
                    "places.location" : 
                        { $near:
                            { $geometry :
                                { type : "2d" ,
                                  coordinates : [ -1 , -2 ] } 
                                },
                                $maxDistance : 2000
                        }
                    }

它给我n次给定的用户(n =用户的每个地方),这就是为什么我决定使用聚合,但我被卡住了。

提前谢谢

修改

我试过$ 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 
}})

并且它返回给我整个用户(包括所有地方,甚至是远处的用户)。

所以我需要在搜索正确的地方之前重新编写文档。

  1. 检索正确的用户(匹配)
  2. 放松用户的每个地方
  3. 然后搜索2公里范围内的每个地方(近/ geonear)
  4. 重塑结果(项目)
  5. 我期待的结果是:

    "result" : [
            {
                    "_id" : "1",
                    "location" : {
                            "latitude" : 1,
                            "longitude" : 1
                    }
            },
            {
                    "_id" : "2",
                    "location" : {
                            "latitude" : 2,
                            "longitude" : 2
                    }
            }
    ]}
    

    问题是我不能在$ geoNear之前使用其他阶段,我的搜索参数必须在“查询”字段中指定。 我收到以下错误:

    $geoNear is only allowed as the first pipeline stage
    

1 个答案:

答案 0 :(得分:7)

您必须使用$geoNear,并且仅在您使用V2.4以后

db.users.aggregate(   
    {$geoNear : {
        near: [-1, -2],
        distanceField: "distance",
        query : {"_id" : "id1"},
        uniqueDocs: true,
        maxDistance : 2000
}})

编辑:编辑后回答问题

波纹管查询会给你位置和距离,但不会检索内部(数组元素)_id

db.users.aggregate(   
{$geoNear : {
    near: [-1, -2],
    distanceField: "distance",
    includeLocs: "location",
    query : {"_id" : "id1"},
    maxDistance : 2000
}},
{$project : {"location" : 1, "_id" : 0, "distance" : 1}} 

请注意添加includeLocs并删除uniqueDocs: true

要检索内部_id,你必须(按照这个例子)展开并有条件地投射左右,但我认为不值得,除非你需要地址而不是_id