NEDB查询在数组上使用$ nin返回误报

时间:2017-08-11 18:48:36

标签: javascript json node.js nedb

我在使用NEDB djb2查询结构时出现问题。

下面的find()查询应该返回所有新消息:发送到指定的find()email组,并且尚未由指定的All读取或发送。

然而,它正在返回误报。例如,平面文件中的两个项目(下面)在结果中返回,尽管被评估的属性数组中的email IS 。我正在使用email运算符,我无法弄清楚我做错了什么?欢迎所有建议:)

$nin

这是平面文件的样子片段。不应该返回这两个,但它们是:/

var email = 'anotheraddress@gmail.com';
var message_query = [];
    message_query.push({$and: [{to: 'All'}, {'data.readBy': {$nin: [email]}}]});
    message_query.push({$and: [{to: email}, {'data.read': {$exists: false}}]});

    message
        .find({
            $and: [
                {$not: {from: email}},
                {$or: message_query}
            ]
        })
        .exec(function (err, results) {

        });

提前致谢

1 个答案:

答案 0 :(得分:1)

问题是$nin运算符 - 它不像在mongo中那样工作。

NEDB的$in运算符的工作方式不同:只有一个操作数可以是一个数组。查看$in的定义($nin毕竟只是对$in的否定)。当它检查数组是否things are equal时,它确保只有一个项是一个数组,即ab[i]都不是数组。如果是,则返回false。 $nin因此返回true - 解释结果中是否存在两个文档。

您可以按照以下方式验证:尝试将[email]更改为["someotheraddress@gmail.com", "anotheraddress@gmail.com", "foo@bar.com"]之类的内容,您会注意到这两个结果消失了 - 证明它没有检查每个元素data.readBy中的data.readBy不在我们提供的列表中,但请检查我们提供的列表中是否存在整个{ $not: { elemMatch }

<强>解决方案 使用message_query.push({ $and: [{ to: "All" }, { $not: { "data.readBy": { $elemMatch: email } } }] });

您可以通过将查询更改为以下内容来解决此问题:

const Datastore = require("nedb");

const db = new Datastore({
  inMemoryOnly: true,
  autoload: false
});

db.insert(
  [
    {
      to: "All",
      toname: "Some Name",
      from: "someaddress@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473320,
      imtype: "msg",
      data: {
        readBy: ["someotheraddress@gmail.com", "anotheraddress@gmail.com"]
      }
    },
    {
      to: "All",
      toname: "Some Name",
      from: "someoneelse@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473420,
      imtype: "msg",
      data: {
        readBy: ["someotheraddress@gmail.com", "anotheraddress@gmail.com"]
      }
    },
    {
      to: "All",
      toname: "Some Name",
      from: "someoneelse@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473420,
      imtype: "msg",
      data: {
        readBy: ["someotheraddress@gmail.com" ]
      }
    },
    {
      to: "foo@bar.com",
      toname: "Some Name",
      from: "someoneelse@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473420,
      imtype: "msg",
      data: {
        readBy: ["someotheraddress@gmail.com", "anotheraddress@gmail.com"]
      }
    },
    {
      to: "anotheraddress@gmail.com",
      toname: "Some Name",
      from: "someoneelse@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473420,
      imtype: "msg",
      data: {
        read: true
      }
    },
    {
      to: "anotheraddress@gmail.com",
      toname: "Some Name",
      from: "someoneelse@gmail.com",
      fromname: "Some other Name",
      message: "A message for all...",
      timestamp: 1502473420,
      imtype: "msg",
      data: {
      }
    }
  ],
  (...args) => {
    var email = "anotheraddress@gmail.com";

    var _list = ["someotheraddress@gmail.com", "anotheraddress@gmail.com", "foo@bar.com"];

    var message_query = [];

    message_query.push({
      $and: [{ to: "All" }, { $not: { "data.readBy": { $elemMatch: email } } }]
    });

    // message_query.push({
    //   $and: [{ to: "All" }, { "data.readBy": { $nin: [email] } }]
    // });

    // message_query.push({
    //   $and: [{ to: "All" }, { "data.readBy": { $nin: _list } }]
    // });

    message_query.push({
      $and: [{ to: email }, { "data.read": { $exists: false } }]
    });

    db.find({
      $and: [ { $not: { from: email } }, { $or: message_query } ]
    }).exec(function(err, results) {
      console.log(JSON.stringify(results, null, 2));
    });

  }
);

以下是要验证的代码:

{{1}}