该文件可能如下:
{
_id: 'abc',
programId: 'xyz',
enrollment: 'open',
people: ['a', 'b', 'c'],
maxPeople: 5
}
我需要返回所有注册为open
且people
的长度小于maxPeople
我让它与$where
:
const
exists = ['enrollment', 'maxPeople', 'people'],
query = _.reduce(exists, (existsQuery, field) => {
existsQuery[field] = {'$exists': true}; return existsQuery;
}, {});
query['$and'] = [{enrollment: 'open'}];
query['$where'] = 'this.people.length<this.maxPeople';
return db.coll.find(query, {fields: {programId: 1, maxPeople: 1, people: 1}});
但我可以通过聚合来做到这一点,为什么会更好?
此外,如果聚合更好/更快,我不明白如何将上述查询转换为使用聚合。我坚持:
db.coll.aggregate([
{$project: {ab: {$cmp: ['$maxPeople','$someHowComputePeopleLength']}}},
{$match: {ab:{$gt:0}}}
]);
更新
基于@chridam回答,我能够实现这样的解决方案,请注意$and
中的$match
,对于那些需要类似查询的人:
return Coll.aggregate([
{
$match: {
$and: [
{"enrollment": "open"},
{"times.start.dateTime": {$gte: new Date()}}
]
}
},
{
"$redact": {
"$cond": [
{"$lt": [{"$size": "$students" }, "$maxStudents" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
]);
答案 0 :(得分:3)
在这种情况下,聚合框架中的 $redact
管道运算符应该适合您。这将以递归方式下降到文档结构中,并根据每个级别的指定条件的评估执行一些操作。这个概念可能有点棘手,但基本上操作符允许您使用 $cond
运算符来处理逻辑条件并使用特殊操作 $$KEEP
“保留”逻辑条件为真的文档或 $$PRUNE
以“删除”条件为false的文档。
此操作类似于具有 $project
管道,该管道选择集合中的字段并创建一个新字段,其中包含逻辑条件查询的结果,然后是后续的 $match
,但 $redact
使用单个管道阶段,该阶段根据查看数据所需的访问权限限制结果集的内容,效率更高
要对enrollment
已打开且people
的长度小于maxPeople
的所有文档运行查询,请添加 $redact
阶段如下::
db.coll.aggregate([
{ "$match": { "enrollment": "open" } },
{
"$redact": {
"$cond": [
{ "$lt": [ { "$size": "$people" }, "$maxPeople" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
答案 1 :(得分:1)
你可以这样做:
$project
创建一个新字段,其中包含people
到maxPeople
$match
与之前的比较结果相符&amp; enrollment
至open
查询是:
db.coll.aggregate([{
$project: {
_id: 1,
programId: 1,
enrollment: 1,
cmp: {
$cmp: ["$maxPeople", { $size: "$people" }]
}
}
}, {
$match: {
$and: [
{ cmp: { $gt: 0 } },
{ enrollment: "open" }
]
}
}])