【问题标题】:How to dynamically build MongoDB Query with multiple OR?如何使用多个 OR 动态构建 MongoDB Query?
【发布时间】:2017-07-12 22:04:47
【问题描述】:

我希望能够使用具有多个 OR 的 Node 动态构建 Mongo 查询。此查询的重点是在数据库中使用多个搜索词进行 AND 搜索。

例如,假设有人想要搜索包含单词“dog”和“cereal”的记录。该查询只会返回在记录中某处包含“dog”和“cereal”的记录(即搜索词可以出现在不同的列中)。

我知道查询最终应该是这样的:

query = {
    $and: [
        {$or: [
            {col1: {$regex: "first", $options: "i"}},
            {col2: {$regex: "first", $options: "i"}}
        ]},
        {$or: [
            {col1: {$regex: "second", $options: "i"}},
            {col2: {$regex: "second", $options: "i"}}
        ]}
    ]
}

但是,我的节点代码不会产生这个。 这是我最接近解决这个问题的方法:

var regexQueryWrapper = {};
regexQueryWrapper["$and"] = [];
var wrapper = {};
wrapper["$or"] = [];
var query = {};
searchTerms.forEach(function(term) {
    searchFields.forEach(function(field) {
        query[field] = {$regex: term, $options: 'i'};
        wrapper["$or"].push(query);
    });
    regexQueryWrapper["$and"].push(wrapper);
});

最好的方法是什么?我是否缺少其他方法?

【问题讨论】:

  • 您是否考虑过为此使用 MongoDB 的 text search?您的用例听起来很合适。
  • @JohnnyHK 我有并且我很想使用它。但是,它不喜欢搜索应用程序的要求。

标签: javascript node.js mongodb mongodb-query


【解决方案1】:

你已经接近了。您似乎在重用对象。下面是一些调整后的代码,用于构建您正在寻找的查询,并在每次 forEach 迭代时重新初始化临时对象:

var regexQueryWrapper = {};
regexQueryWrapper["$and"] = [];

searchTerms.forEach(function(term) {

    var wrapper = {"$or": []};

    searchFields.forEach(function(field) {
        var query = {};
        query[field] = {$regex: term, $options: 'i'};
        wrapper["$or"].push(query);
    });

    regexQueryWrapper["$and"].push(wrapper);

});

还有一个使用map的替代实现:

var query = {"$and": searchTerms.map(function(term) {

    return {"$or": searchFields.map(function(field) {

        var o = {};
        o[field] = {"$regex": term, "$options": "i"};
        return o;

    })};

})};

【讨论】:

    【解决方案2】:

    我认为你过于复杂了。

    通过考虑您主要操作两个嵌套数组(andor)这一事实,逐步构建您的查询。

    使用一个推送数组的函数和另一个返回数组的函数,NodeJS 代码将是:

    query = {and: []};
    
    function add_and(or_query) {
     query["and"].push({or: or_query});
    }
    
    function build_or_query(term) {
     return [
       {col1 : {$regex: term, $options: "i"}},
       {col2: {$regex: term, $options: "i"}}
     ]
    }
    

    在您的代码中重命名并使用您认为合适的函数来管理用户输入事件。你也可以根据需要合并它们,确保代码非常紧凑:

    function add_and(term) {
     query["and"].push({or: [
       {col1 : {$regex: term, $options: "i"}},
       {col2: {$regex: term, $options: "i"}}
     ]});
    }
    

    使用like(两个功能):

    add_and(build_or_query('test1'));
    add_and(build_or_query('test2'));
    

    或喜欢(一个功能):

    add_and('test1');
    add_and('test2');
    

    结果:

    { 
      and: [ 
        { or: [ { col1: { '$regex': 'test1', '$options': 'i' } },
                { col2: { '$regex': 'test1', '$options': 'i' } } ] },
        { or: [ { col1: { '$regex': 'test2', '$options': 'i' } },
                { col2: { '$regex': 'test2', '$options': 'i' } } ] } 
      ]
    }
    

    【讨论】:

    • 当我在this website 上尝试您的解决方案时,我被告知这是无效的 javascript。这很奇怪,因为在我看来一切都是正确的......
    • PS:我在你的网站上试过,它可以工作,当你在网站上测试时删除“build_or_query(”是最短的解决方案。我最初更喜欢使用两个函数,以提供更大的灵活性,所以我保留了答案中的长解决方案。
    猜你喜欢
    • 2019-07-01
    • 2019-03-25
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2015-08-27
    相关资源
    最近更新 更多