请考虑以下事项:
db.stores.aggregate(
{ $project: {
_id: 0,
in_radius: {
$cond: {
if: <geoWithinExpression>,
then: 1,
else: 0
}
}
}
})
geoWithinExpression实际上是:
$match: {
location: {
$geoWithin: {
$center: [[lat, lon], radius]
}
}
}
我这样做,所以我可以在结果集上使用$ group来计算该半径中的商店数量。 (我正在使用$ project,因为我想做更多像这样的自定义列并一次性返回它们。)
这甚至可能吗?
答案 0 :(得分:2)
由于一些非常合理的原因,这是不可能的。
虽然我看到你想要实现的目标,但基本前提是$match
本身就是管道阶段的标识符,因此只能以这种方式使用。
这里的第二种情况是,您似乎正在寻找的是某种“运算符”,它实际上会以逻辑(真/假)方式返回$geoWithin
类型的结果用于$project
或$group
阶段。在这种情况下,“地理空间”查询需要使用索引,因此,聚合管道中唯一可以使用索引的位置是第一阶段,通常是“应该” “成为$match
阶段。
如上所述,这个概念是非常合理的,因为除了初始流水线阶段之外,你真的会有任何与创建索引的文档实际匹配的东西。新文档“副本”仅存在于管道处理中,因此没有关联的索引。
虽然很明显您的目的是“测试”各种集合中的位置数据,但最好的方法是使用多个查询来执行此操作并将结果合并到代码中或以其他方式写入另一个集合。
答案 1 :(得分:0)
最终,我使用聚合界面,使用distanceField
阶段$geoNear
中$group
添加的$cond
,确切地返回了我需要的内容:
[
{
$geoNear: {
near: [<lon>,<lat>],
distanceField: "distance",
spherical: true,
maxDistance: <extended_radius_distance_in_radians>
distanceMultiplier: earthRadius
}
},
{
$group:{
_id: "default",
in_default_radius: { $sum: { $cond: { if: { $lt: ["$distance", <default_radius>] }, then: 1, else: 0 } } },
in_extended_radius: { $sum: 1 },
in_extended_radius_with_a_cond: { $sum: { $cond: { if: { $eq: ["$something", "something"] }, then: 1, else: 0 } } }
}
}
]