如何使用多个OR动态构建MongoDB查询?

时间:2017-07-12 22:04:48

标签: javascript node.js mongodb mongodb-query

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

例如,假设某人想要搜索包含单词" dog"和谷物。"该查询只会返回包含" dog"和"谷物"记录中的某个位置(即搜索词可以出现在不同的列中)。

我知道查询应该看起来像这样:

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);
});

最好的方法是什么?我缺少一种不同的方法吗?

2 个答案:

答案 0 :(得分:1)

我认为你过于复杂了。

通过考虑您主要操作两个嵌套数组(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' } } ] } 
  ]
}

答案 1 :(得分: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;

    })};

})};