首页 > 解决方案 > 如何使用 MongoDB 聚合有条件地匹配搜索表单中不为空的字段?

问题描述

我的网站上有一个带有 10 多个可选搜索参数的大型搜索表单。我需要从 MongoDB 返回与每次搜索中存在的任何表单字段匹配的所有文档。

获得所需结果的一种方法是按顺序为非空搜索字段的每个可能组合编写 if else 语句,但必须有更好的方法。

    ex.
    const sQ = new TMDLs(request.body);


    }else if(sQ.Basin && sQ.Water_Body_Name && sQ.Water_Body_ID){
        searchData = await TMDLs.aggregate([
            { $match: { $text: {$search: `\"${sQ.Basin}\"`}}},
            { $match: { Water_Body_Name: sQ.Water_Body_Name}},
            { $match: { Water_Body_ID: sQ.Water_Body_ID}}

        ]);
    }else if(sQ.Basin && sQ.Water_Body_Name){
        searchData = await TMDLs.aggregate([
            { $match: { Basin: sQ.Basin }},
            { $match: {Water_Body_Name: sQ.Water_Body_Name}}
        ]);

上面的代码有效,但尝试非空搜索参数的每种组合是不切实际的。我需要聚合结果来返回与非空搜索字段匹配的所有记录。

我已经尝试过 $ifNull、$exists、$group、$project 和许多其他条件运算符,但我找不到任何可以解决这个问题的方法。

标签: mongodbformsaggregation-frameworkmongoose-schema

解决方案


构建此问题的一种方法是列出所有搜索并过滤掉非空搜索:

const criteria = [
            sQ.Basin != null && { $text: {$search: `\"${sQ.Basin}\"`}}},
            sQ.Water_Body_Name != null && { Water_Body_Name: sQ.Water_Body_Name}},
            sQ.Water_Body_ID != null && { $match: { Water_Body_ID: sQ.Water_Body_ID}}
            sQ.Basin != null && { Basin: sQ.Basin },
            ...
].filter(Boolean)

拥有这些条件后,您可以使用$and将它们组合成一个$match阶段(相当于多个串行$match阶段)。

TMDLs.aggregate([
  {$match: {$and: criteria}},
  ...
])

推荐阅读