仅当字符串不为空时,才运行特定的$match查询



我正在尝试实现对集合中文档的搜索。$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
        }
    }
])

最新更新