简单数组上的$ elemMatch投影

时间:2014-10-01 12:25:12

标签: mongodb mongodb-query

想象一下电影的集合(存储在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运算符(在聚合框架内),但是如果买家有数千个值(在匹配之前基本上将每个文档扩展到内存中的数千个副本),这似乎非常浪费。< / p>

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

2 个答案:

答案 0 :(得分:1)

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

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

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

此操作符已添加到MongoDB 2.6中。

答案 1 :(得分:1)

这里不太确定您的意图,但您不需要更改结构只是为了在投影中使用$elemMatch。您可以这样发出:

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

这会将返回的数组元素过滤为仅显示的“买方”,或者不存在任何不存在的内容。确实指出这里使用的$eq运算符实际上没有记录,但确实存在。因此,可能不会立即明确表示您可以通过这种方式构建条件。

对我来说似乎有点浪费,因为无论“买家”是否存在,你都会回归“一切”。因此,“查询”似乎比投影更合乎逻辑:

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

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

db.movies.find({ "buyers": 2910 },{ "buyers.$": 1})
聚合框架中的

Set operators$project提供了更多选项,可以更改文档。但是如果你只是想知道某人是否“买了”这个项目,那么“查询”似乎是合乎逻辑且最快的方式。