mongodb-queries是否有类似非任何运算符的东西?
我有以下设置:
const ConstructQuestion = new Schema({
answerType: String,
text: String,
});
const Construct = new Schema({
name: String,
description: String,
questions: [ConstructQuestion],
});
我还有一系列ConstructQuestion-ID。我现在尝试查询所有Constructs,其中包含_id
不在我的ConstructQuestionID-Array中的任何问题。
换句话说:我希望所有包含_id
不是
我可以使用$in
来查询我想要的内容,_id
查询所有构造,其中$nin
任何我的ID中的ID阵列。遗憾的是return this.construct.aggregate()
.group({
_id: '$_id',
questions_id: {$push: '$questions._id'},
construct: {$first: '$$ROOT'},
})
.unwind('$questions_id')
.project({
construct: true,
questions_id: true,
check: {
$cmp: [{
$size: {$setIntersection: ['$questions_id', usedQuestionIds]},
}, {
$size: '$questions_id',
}],
},
})
.match({check: {$lt: 0}})
.exec()
.then((results) => {
const constructs = results.map((result) => {
return result.construct;
});
})
不是答案,因为它与包含我的ID-Array中的所有问题的Construct不匹配
修改
非常精确:我正在寻找一个查询,它会在我的ID-Array
中为我提供至少包含一个ID为不的问题的所有构造结果:
在Bertrand回答的帮助下,我的猫鼬解决方案现在看起来像这样:
group
改进:
在每次创建/更新后将questionIds作为数组直接添加到Construct后,我可以删除unwind
和return this.construct.aggregate({
$addFields: {
check: {
$cmp: [{
$size: {$setIntersection: ['$questionIds', usedQuestionIds]},
}, {
$size: '$questionIds',
}],
},
}})
.match({check: {$lt: 0}})
.exec()
.then((constructs) => {
});
阶段,因此我的代码现在看起来像这样:
$project
再次感谢Bertrand提示
改进2
同样,作为Bertrand的提示,$match
和$redact
可以(在这种情况下)合并到return this.construct.aggregate({
$redact: {
$cond: {
if: {
$lt: [
{$size: {$setIntersection: ['$questionIds', usedQuestionIds]}},
{$size: '$questionIds'}
]
},
then: '$$KEEP',
else: '$$PRUNE'
}
}})
.exec()
.then((constructs) => {
});
,现在代码如下所示:
$size
改进3
我发现,我可以使用$setDifference和一个$setInsersection
代替$size
和两个return this.construct.aggregate({
$redact: {
$cond: {
if: {
$gt: [{$size: {$setDifference: ['$questionIds', usedQuestionIds]}}, 0]
},
then: "$$KEEP",
else: "$$PRUNE"
}
}})
.exec()
.then((constructs) => {
});
。代码现在看起来像这样:
package package_with_global is
acc integer := 0;
end;
答案 0 :(得分:1)
var input = ["58c20f6d95b16e3046ddd7e9", "58c20f6d95b16e3046ddd7eb", "58c20f6d95b16e3046ddd7ec"];
Data.find({
"questions._id": {
"$not": {
"$all": input
}
}
}, function(err, res) {
console.log(res);
});
它将返回所有未在输入input
数组中指定所有问题的文档。如果选择了文档,则表示input
数组中至少有一个问题不在文档中。
如果您希望交集与questions
文档完全匹配,您可以使用聚合中可用的setIntersection
来确定两个数组共有的元素,并根据以下内容做出决定:
var array = [
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7e9"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7ea"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7eb"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7ec")
];
Const.aggregate([{
$group: {
"_id": "$_id",
"questions_id": {
$push: "$questions._id"
},
"document": { $first: "$$ROOT" }
}
}, {
$unwind: "$questions_id"
}, {
$project: {
document: 1,
questions_id: 1,
check: {
$cmp: [{
$size: {
$setIntersection: ["$questions_id", array]
}
}, {
$size: "$questions_id"
}]
}
}
}, {
$match: {
check: {
"$lt": 0
}
}
}], function(err, res) {
console.log(res);
});
第一个$group
& $unwind
负责构建questions._id
数组。比较在下一个$project
中执行,交叉点大小和questions._id
的大小。
您可以使用$redact
简化$project
+ $match
,以保证dcouments符合条件。使用新添加的questionIds
字段,它更简单:
var array = [
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7e9"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7ea"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7eb"),
new mongoose.mongo.ObjectId("58c20f6d95b16e3046ddd7ec")
];
Const.aggregate([{
$redact: {
$cond: {
if: {
$lt: [{
$size: {
$setIntersection: ["$questionIds", array]
}
}, {
$size: "$questionIds"
}]
},
then: "$$KEEP",
else: "$$PRUNE"
}
}
}], function(err, res) {
console.log(res);
});