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

标签 javascript json node.js nedb

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

下面的 find() 查询应该返回所有新消息:发送到指定的 emailAll 组,但尚未发送通过指定的 email 阅读或发送。

但是,它返回误报。例如,尽管 email IS 在被评估的属性数组中,但结果中返回了平面文件(如下)中的两项。我正在使用 $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) {

        });

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

...

{ 
  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 的定义(毕竟 $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));
    });

  }
);

关于javascript - NEDB 查询在数组上使用 $nin 返回误报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45641983/

相关文章:

javascript - HTML : Text width is different than summation of its character's width

javascript - jqgrid 在重新加载时保留自定义帖子参数

javascript - 从 json 获取值到 angularjs 对象

java - Jackson 用空对象反序列化数组

node.js - sendfile 有问题

javascript - d3 在附加的 div 之后附加空格

python - Messenger JSON 中的编码

javascript - 在服务器端实现 Paper.js 螺旋光栅示例

node.js - .createreadstream 值到字符串变量

javascript - 无法打开与同一 SockJS 端点的多个连接