【发布时间】:2023-02-10 18:32:05
【问题描述】:
语境 :
我正在尝试构建一个显示 POI 的架构,随着时间的推移,这些 POI 可以位于不同的已知位置。
我有 2 个系列,
泊
{
_id: ObjectId,
name: string
}
地点
_id: ObjectId,
point: {
type: 'Point',
coordinates: Array<number>
},
poi: ObjectId // Reference to Poi
用例:
所以我正在尝试构建一个查询
- 输入中心坐标+半径
- 并返回比半径内匹配的Pois
- 只有他们最近的位置
- 按距离排序
理想情况下,具有以下输出:
[
{
_id: ObjectId(AE54232),
name: 'Some poi',
location: {
_id: ObjectId(BFE5423),
point: {
type: 'Point',
coordinates: [3, 50]
},
distance: 3
}
}
]
试图
仔细阅读文档,我使用了这个组合:
// Keep only locations within radius,
// output 'distance'
// and sort by distance
{
$geoNear: {
near: nearCenter,
key: 'point',
distanceField: 'distance',
maxDistance: nearRadius,
spherical: true,
},
},
// Keep only first (assumed 'nearest')
// location of each poi
{
$group: {
_id: '$poi',
location: {
$first: '$$ROOT'
}
}
},
// Retrieve poi
{
$lookup: {
from: 'pois',
localField: '_id',
foreignField: '_id',
as: 'poi',
},
},
// Flatten poi
{
$unwind: {
path: '$poi',
},
},
// Push poi at the root,
// and put location inside 'location'
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$poi",
{ location: "$location" },
]
},
}
},
所以总结一下:
$geoNear$first(by poi)$lookup(poi)$unwind(poi)-
$replaceRoot(poi { location })
麻烦
我遇到了一种奇怪的行为,查询基本上可以正常工作;除了它不是按距离排序:pois 和他们的location 以不稳定和非确定性的顺序出现!
我试着一步一步地评论每一步,显然这是导致“洗牌”的$first。这是令人惊讶的,因为文档指出:
输出文档为了从最近到最远的指定点。
返回将表达式应用于一组文档中的第一个文档所产生的值。只有当文件有意义有明确的顺序.
修复尝试
我的想法是
$first期望实际的$sort而不是隐式的$geoNear排序;所以我试着像这样在两者之间插入一个$sort:{ $sort: { 'distance': 1, }, },像这样介于两者之间:
$geoNear$sort(distance)<== 这里$first(by poi)$lookup(poi)$unwind(poi)$replaceRoot(poi { location })但它给了我完全相同的结果!
唯一有用的是在最后添加一个
$sort,就像这样{ $sort: { 'location.distance': 1, }, },
$geoNear$first(by poi)$lookup(poi)$unwind(poi)$replaceRoot(poi { location })$sort(location.distance)<== 这里但我担心它在大型数据集上可能会出现性能问题
问题
有什么办法可以实现这个逻辑
- 过滤$geoNear(保持距离)
- $group by referenced document,只保留“最近的”
不丢失 $geoNear 订单?
【问题讨论】:
-
由于没有样本数据,问题不是很清楚。多个位置可以引用同一个
poi吗?如果您提供一些示例文档以及它们的预期结果,将会更清楚 -
如果每个
poi可以有几个位置,而不是分组后,poi,distance的排序无效。你应该在$group阶段之后再次按distance排序
标签: mongodb group-by aggregation-framework gis geonear