我希望能够使用具有多个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);
});
最好的方法是什么?我缺少一种不同的方法吗?
答案 0 :(得分:1)
我认为你过于复杂了。
通过考虑您主要操作两个嵌套数组(and
和or
)的事实,逐步构建查询。
使用推送数组的函数和另一个返回数组的函数,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;
})};
})};