mongo查找文档,其中数组中的至少一个项目不在另一个项目中

时间:2015-01-05 15:00:50

标签: javascript regex mongodb mongodb-query

我在mongo中有这个问题,我想查询(常规mongo查询,使用终端)查找字段为空的所有文档,或者至少有一个与数组不匹配的值正则表达式。

我的文件有以下模式:

{
  "id": "20",
  "array": ["abc123", "abc456", "def123", "ghi123"]
}

{
  "id": "21",
  "array": ["abc123", "abc456", "def123"]
}

我匹配它们的数组看起来像这样:

[new RegExp(abc), new RegExp(def)]

查询的结果应该只是第一个文档,因为它包含" ghi123",它与数组中的任何正则表达式都不匹配。

我知道有像$ all,$ elementMatch,$等运营商来构建这个查询,但到目前为止,我还没找到合适的解决方案,而且我已经被困了很长一段时间了...我找到了其他有用的StackOverflow页面,可能会得到正确的答案,但我还没能将它应用到我的问题中。这个似乎最有用:

Check if every element in array matches condition

有没有人知道如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

这实际上只是一个正则表达式问题,因为所有逻辑都可以在那里处理:

db.collection.find({ "array": /^(?!abc|def)/ })

这基本上是一个否定的断言,即被测试的元素匹配由|分隔的条件,这意味着

由于第一个文档是唯一一个具有不符合条件的数组元素的文档,因此它是唯一一个在此处评估为true的情况。

正则表达式通常是从基础“字符串”构造的,因此考虑到以下“列表”的表示,这应该不难理解:

var args = ["abc","def"];

var exp = "^(?!" + args.join("|") + ")";
db.collection.find({ "array": new Regexp(exp) });

甚至:

var args = ["abc","def"];
var inclause = { "$in": [ ] };

inclause["$in"] = args.map(function(arg) {
    return new Regexp( "^(?" + arg + ")" );
});

db.collection.find({ "array": inclause });

但第一种形式通常应该更有效率。