Javascript NEDB查询返回数组上带有$nin的误报

Javascript NEDB查询返回数组上带有$nin的误报,javascript,json,node.js,nedb,Javascript,Json,Node.js,Nedb,我在使用NEDBfind()查询结构时遇到问题 下面的find()查询应返回所有新邮件:发送到指定的电子邮件或all组,但未被指定的电子邮件读取或发送 然而,它正在返回假阳性。例如,平面文件(下面)中的两个项目将在结果中返回,尽管电子邮件在正在评估的属性数组中。我正在使用$nin运算符,但我无法确定我做错了什么?欢迎所有建议:) 下面是平面文件的一个片段。这两个不应返回,但它们是:/ ... { to: 'All', toname: 'Some Name', from: 'som

我在使用NEDB
find()
查询结构时遇到问题

下面的
find()
查询应返回所有新邮件:发送到指定的
电子邮件
all
组,但未被指定的
电子邮件
读取或发送

然而,它正在返回假阳性。例如,平面文件(下面)中的两个项目将在结果中返回,尽管
电子邮件
在正在评估的属性数组中。我正在使用
$nin
运算符,但我无法确定我做错了什么?欢迎所有建议:)

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

...

{ 
  to: 'All',
  toname: 'Some Name',
  from: 'someaddress@gmail.com',
  fromname: 'Some other Name',
  message: 'A message for all...',
  timestamp: 1502473320,
  imtype: 'msg',
  _id: 'K66iP3dZHbYTfGgK',
  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',
  _id: 'K66iP3dZNyNxfGgK',
  data:
   { readBy:
      [ 'someotheraddress@gmail.com',
        'anotheraddress@gmail.com' ] } 
}

...

提前感谢

问题在于
$nin
操作符-它不像在mongo中那样工作

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

您可以按如下方式进行验证:尝试将
[email]
更改为类似
[”someotheraddress@gmail.com", "anotheraddress@gmail.com", "foo@bar.com“]
,您会注意到这两个结果消失了-证明它不会检查
数据中的每个元素。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));
    });

  }
);

早上好,玛纳斯!感谢您的详细回复。我现在将尝试确认您的答案。亚当,您好。当然:)您的答案确实正确!感谢您花时间研究此问题。已标记为正确,但在接下来的12小时内无法颁发赏金!很高兴我能提供帮助:)
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));
    });

  }
);