我正在尝试实现对集合中文档的搜索。$match阶段中的一个查询检查列表中是否有任何内容与JS中的另一个列表匹配(不在文档中(。
但是,我只想在列表中包含内容时运行该查询。如果它是空的,那么就忽略它。
本质上类似于在过滤器中选择选项。如果你选择了什么,它会搜索它,如果你什么都不选择,它就不会以此为基础进行限制。
个人文件:
{
name: String,
dob: Date,
gender: String,
favoriteColors: [{
color: String,
otherInfo: String
}]
}
我的管道:
let colors = ["red", "blue", "green"];
collection.aggregate([
{$match: {
gender: "male",
//run below only if colors array is not empty
favoriteColors: {
$elemMatch: {
color: {
$in: colors
}
}
}
}}
])
只有在数组不为空的情况下,我怎么能基本上只运行聚合的那部分?我真的不想使用if语句,并基于两个不同的条件两次编写相同的聚合。有可能做到这一点吗?
您可以使用$cond这样的东西:
let colors = [ ... ]
db.collection.aggregate([
{
$match: {
$expr: {
$and: [
{
$eq: [
"$gender",
"male"
]
},
{
$cond: [
{
$gt: [
colors.length,
0
]
},
{
$gt: [
{
$size: {
$setIntersection: [
{
$map: {
input: "$favoriteColors",
as: "color",
in: "$$color.color"
}
},
colors
]
}
},
0
]
},
{}
]
}
]
}
}
}
])
但是,如果您已经在使用代码,为什么不将相同的逻辑移到js中呢?:
let colors = [ ... ];
let conds = [
{
"gender": "Male"
}
];
if (colors.length) {
conds.push({
"favoriteColors.color": {$in: colors}
})
}
db.collection.aggregate([
{
$match: {
$and: conds
}
}
])