问题在于$nin
操作员 - 它不像在 mongo 中那样工作。
NEDB 的$in
操作符工作方式不同:只有一个操作数可以是数组。查看$in
(毕竟$nin
只是对的否定)的定义。$in
当它检查数组的事物是否相等时,它确保只有一项是数组,即既不是数组也不a
是b[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));
});
}
);