【问题标题】:$elemMatch Projection on a Simple Array简单数组上的 $elemMatch 投影
【发布时间】:2014-10-01 12:25:11
【问题描述】:

想象一组电影(存储在 MongoDB 集合中),每部电影看起来像这样:

{ 
    _id: 123456,
    name: 'Blade Runner',
    buyers: [1123, 1237, 1093, 2910]
}

我想得到一个电影列表,每一个都有一个指示买家 2910(例如)是否购买了它。

有什么想法吗?

我知道我可以将 [1123, 1237, 1093, 2910] 更改为 [{id:1123}, {id:1237}, {id:1093}, {id:2910}] 以允许使用 $elemMatch在投影中,但不希望触摸结构。

我也知道我也许可以使用 $unwind 运算符(在聚合框架内),但在买方有数千个值的情况下这似乎非常浪费(基本上在匹配之前将每个文档分解成内存中的数千个副本)。

还有其他想法吗?我在这里错过了一些非常简单的东西吗?

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    您可以使用$setIsSubset 聚合运算符来执行此操作:

    var buyer = 2910;
    db.movies.aggregate(
        {$project: {
            name: 1,
            buyers: 1,
            boughtIt: {$setIsSubset: [[buyer], '$buyers']}
        }}
    )
    

    这将为您提供添加了boughtIt 字段的所有电影文档,该字段指示buyer 是否包含在电影的buyers 数组中。

    此运算符是在 MongoDB 2.6 中添加的。

    【讨论】:

      【解决方案2】:

      不太确定您的意图,但您无需更改结构即可在投影中使用$elemMatch。你可以这样发出:

      db.movies.find({},{ "buyers": { "$elemMatch": { "$eq": 2910 } } })
      

      这会将返回的数组元素过滤为仅指示的“买家”,或者在不存在的地方过滤。确实需要指出,此处使用的 $eq 运算符实际上并未记录在案,但它确实存在。因此,您可能无法立即明确是否可以以这种方式构造条件。

      这对我来说似乎有点浪费,因为无论“买家”是否在场,您都会退回“所有东西”。所以“查询”似乎比投影更合乎逻辑:

      db.movies.find({ "buyers": 2910 })
      

      并且可以选择只保留匹配的结果:

      db.movies.find({ "buyers": 2910 },{ "buyers.$": 1})
      

      聚合框架中的Set operators 为您提供更多选项,$project 可以做更多的更改文档。但是,如果您只想知道是否有人“购买”了该商品,那么“查询”似乎是最合乎逻辑且最快的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-21
        • 2015-05-26
        • 2016-10-09
        • 2011-05-24
        • 2014-07-04
        • 1970-01-01
        • 1970-01-01
        • 2022-01-14
        相关资源
        最近更新 更多