MongoDB查询聚合/分组依据和geometry / location / geoNear查询

问题描述 投票:0回答:1

我试图在某个位置获取具有几何的文档,但是只想每个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
      ]
   }
}
mongodb
1个回答
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提取数组的第一项。

这会产生:

{
  "_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 ] }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.