【问题标题】:MongoDB $match inside $cond$cond 内的 MongoDB $match
【发布时间】:2014-07-19 11:03:58
【问题描述】:

考虑以下几点:

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 是因为我想做更多像这样的自定义列并一次性返回它们)。

这可能吗?

【问题讨论】:

标签: mongodb aggregation-framework


【解决方案1】:

这是不可能的,原因有很多,这些原因都非常合理。

  • 虽然我看到了您要实现的目标,但基本前提是 $match 本身就是管道阶段的标识符,因此只能以这种方式使用。

  • 这里的第二种情况是,您似乎正在寻找某种“运算符”,它实际上会以逻辑(真/假)方式返回 $geoWithin 类型的结果,用于$project$group 阶段。作为一个概念,“地理空间”查询需要使用索引,因此,聚合管道中唯一可以使用索引的地方是第一阶段,通常“应该"成为$match的舞台。

如上所述,这个概念是非常合理的,因为在最初的管道阶段,您真的会拥有与创建索引的文档实际匹配的任何内容。新文档“副本”仅存在于管道处理中,因此没有关联的索引。

虽然很明显您的意图是“测试”不同集合中位置的数据,但最好的方法是使用多个查询来执行此操作并将结果组合到代码中或以其他方式写入另一个集合。

【讨论】:

  • 感谢您的回答,它确实有助于弄清楚事情是如何运作的 :)
【解决方案2】:

最终,我能够使用聚合接口在$group 阶段的$cond 中使用$geoNear 添加的distanceField 准确返回我需要的内容:

[
  {
    $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 } } }
    }
  }
]

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 1970-01-01
    • 2019-08-07
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2021-10-16
    相关资源
    最近更新 更多