MongoDB查询aggreate / group by和geometry / location / geoNear查询

时间:2018-03-01 07:03:12

标签: mongodb

我正在尝试在某个位置获取包含几何体的文档,但是只想每个UUID返回一个文档。对于这个项目,在大多数情况下,每个UUID都有许多文档与$ near选择器匹配,因此我们得到许多具有相同UUID的文档。

任何人都可以协助完成以下查询,因此每个uuid只返回一个文档(最近的"日期")?

db.device.find(
   {
     location:
       { $near :
          {
            $geometry: { type: "Point",  coordinates: [ -73.9667, 40.78 ] },
            $minDistance: 1000,
          }
       }
   }
)

以下是该集合的一个示例:

{  
   "_id":ObjectId("5a4f1ff0fc6ded723265e6b0"),
   "uuid":"user1",
   "date": "2018-01-20 11:58:29.000",
   "location":{  
      "type": "Point",
      "coordinates":[   
            //remove for demo sake
      ]
   }
},
{  
   "_id":ObjectId("5a62a245ce689f68245450a7"),
   "uuid":"user2",
   "date": "2018-01-20 11:58:07.000",
   "location":{  
      "type": "Point",
      "coordinates":[   
            //remove for demo sake
      ]
   }
},
{  
   "_id":ObjectId("5a62a20fce689f7a14648c62"),
   "uuid":"user1",
   "date": "2018-01-20 11:58:39.000",
   "location":{  
      "type": "Point",
      "coordinates":[   
            //remove for demo sake
      ]
   }
},
{  
   "_id":ObjectId("5a62a205ce689f7039203923"),
   "uuid":"user1",
   "date": "2018-01-20 11:58:49.000",
   "location":{  
      "type": "Point",
      "coordinates":[   
            //remove for demo sake
      ]
   }
},
{  
   "_id":ObjectId("5a62a277ce689f703a3eacb3"),
   "uuid":"user2",
   "date": "2018-01-20 11:58:59.000",
   "location":{  
      "type": "Point",
      "coordinates":[   
            //remove for demo sake
      ]
   }
}

1 个答案:

答案 0 :(得分:2)

执行此类heavier操作时,您可以切换到使用aggregation管道。

使用此输入:

{  
  "uuid": "user1",
  "date": "2018-01-20 11:58:29.000",
  "location": { "type": "Point", "coordinates":[-0.17818, 51.15609] }
},
{  
  "uuid": "user2",
  "date": "2018-01-20 11:58:07.000",
  "location": { "type": "Point", "coordinates":[2.35944, 48.72528] }
},
{
  "uuid": "user1",
  "date": "2018-01-20 11:58:39.000",
  "location": { "type": "Point", "coordinates": [1.45414, 43.61132] }
},
{
  "uuid": "user1",
  "date": "2018-01-20 11:58:49.000",
  "location": { "type": "Point", "coordinates":[-6.24889, 53.33306] }
},
{  
  "uuid": "user2",
  "date": "2018-01-20 11:58:59.000",
  "location": { "type": "Point", "coordinates":[-3.68248, 40.47184] }
}

使用此索引:

db.device.createIndex( { location : "2dsphere" } )

此管道应该执行您想要的任务:

db.device.aggregate([
     { $match: { location: { $geoWithin: { $centerSphere: [ [ -0.17818, 51.15609 ], 0.1232135647961246 ] } } } },
     { $sort: { "date": -1 } },
     { $group: { _id: { uuid: "$uuid" }, users: { $push: { "uuid": "$uuid", "date": "$date", "location": "$location" } } } },
     { $project: { user: { $arrayElemAt: ["$users", 0] } } }
  ])

我首先将find/$near运算符调整为等效聚合($geoWithin / $centerSphere)。它匹配0.123弧度范围内的位置(488公里(0.123 * 3963.2))。

然后我直接按日期排序,这样当文档将按用户分组时,我将能够轻松选择每个用户的第一个。

然后我按用户分组。

最后对于每个用户,因为我有$group生成的值,这是一个用户文档数组(已排序),我只是用$arrayElemAt提取数组的第一项。< / p>

这会产生:

{
  "_id" : { "uuid" : "user2" },
  "user": {
    "uuid": "user2",
    "date": "2018-01-20 11:58:07.000",
    "location": { "type": "Point", "coordinates": [ 2.35944, 48.72528 ] }
  }
}
{
  "_id": { "uuid" : "user1" },
  "user": {
    "uuid": "user1",
    "date": "2018-01-20 11:58:49.000",
    "location": { "type": "Point", "coordinates": [ -6.24889, 53.33306 ] }
  }
}
相关问题