NEDB查询返回错误肯定与数组$ nin

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

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

但是,它正在返回误报。 例如,平面文件(下面)中的两个项目被返回到结果中,尽pipe被评估的属性数组中的email为。 我正在使用$nin操作符,而且我无法弄清楚我在做什么错误? 所有的build议欢迎:)

 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的否定)。 当它检查数组是否相等时 ,它确保只有一个项是一个数组,即ab[i]都不能是数组。 如果是,则返回false。 $nin因此返回true – 解释结果中是否存在这两个文档。

你可以validation这个如下:尝试改变[email]["someotheraddress@gmail.com", "anotheraddress@gmail.com", "foo@bar.com"] ,你会注意到,这两个结果消失- certificate它不检查data.readBy每个元素是否不在我们提供的列表中,而是检查整个data.readBy是否存在于我们提供的列表中。

解决scheme使用{ $not: { elemMatch }

您可以通过将您的查询更改为以下来解决该问题:

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

以下是validation的代码:

 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)); }); } );