use*_*818 15 mongoose mongodb mongodb-query
我有一个与此类似的架构.
{id: Number,
line_items: [{
id: String,
quantity: Number,
review_request_sent :Boolean
}],
total_price: String,
name: String,
order_number: Number
}
Run Code Online (Sandbox Code Playgroud)
我想要找到的是没有为数组中的所有项设置字段review_request_sent的所有元素.
例
{
id: 1,
line_items: [
{
id: 43,
review_request_sent: true
}
]
},
{
id: 2,
line_items: [
{
id: 1,
review_request_sent: false
},
{
id: 39
},
]
},
{
id: 3,
line_items: [
{
id: 23,
review_request_sent: true
},
{
id: 85,
review_request_sent: true
},
{
id: 12,
review_request_sent: false
}
]
}
Run Code Online (Sandbox Code Playgroud)
我想要一个查询/查找的帮助,它只返回第二个文档,因为它的数组中的所有项目都没有review_request_sent字段.
Bla*_*ven 26
你基本上想要$elemMatch和$exists操作符,因为这将检查每个元素以查看条件"字段不存在"对于任何元素是否为真:
Model.find({
"line_items": {
"$elemMatch": { "review_request_sent": { "$exists": false } }
}
},function(err,docs) {
});
Run Code Online (Sandbox Code Playgroud)
只返回第二个文档,因为该字段不存在于其中一个数组子文档中:
{
"id" : 2,
"line_items" : [
{
"id" : 1,
"review_request_sent" : false
},
{
"id" : 39
}
]
}
Run Code Online (Sandbox Code Playgroud)
请注意,这与此形式"不同":
Model.find({
"line_items.review_request_sent": { "$exists": false }
},function(err,docs) {
})
Run Code Online (Sandbox Code Playgroud)
在那里询问"全部"数组元素是否包含此字段,当文档至少有一个具有该字段的元素时,这不是真的.因此,$eleMatch使条件针对"每个"数组元素进行测试,从而得到正确的响应.
如果你想更新这个数据,以便找到任何不包含这个字段的数组元素,那么接收那个值为false(推测)的字段,你甚至可以写一个这样的语句:
Model.aggregate(
[
{ "$match": {
"line_items": {
"$elemMatch": { "review_request_sent": { "$exists": false } }
}
}},
{ "$project": {
"line_items": {
"$setDifference": [
{"$map": {
"input": "$line_items",
"as": "item",
"in": {
"$cond": [
{ "$eq": [
{ "$ifNull": [ "$$item.review_request_sent", null ] },
null
]},
"$$item.id",
false
]
}
}},
[false]
]
}
}}
],
function(err,docs) {
if (err) throw err;
async.each(
docs,
function(doc,callback) {
async.each(
doc.line_items,
function(item,callback) {
Model.update(
{ "_id": doc._id, "line_items.id": item },
{ "$set": { "line_items.$.review_request_sent": false } },
callback
);
},
callback
);
},
function(err) {
if (err) throw err;
// done
}
);
}
);
Run Code Online (Sandbox Code Playgroud)
凡.aggregate()结果不仅匹配的文件,但过滤掉来自数组,其中场不存在,从而只返回特定的子文档的"ID"的内容.
然后循环.update()语句匹配每个文档中的每个找到的数组元素,并在匹配的位置添加缺少的字段和值.
通过这种方式,您将在每个文档的所有子文档中都显示该字段.
如果你想做这样的事情,那么改变你的模式也是明智的,以确保该字段始终存在:
{id: Number,
line_items: [{
id: String,
quantity: Number,
review_request_sent: { type: Boolean, default: false }
}],
total_price: String,
name: String,
order_number: Number
}
Run Code Online (Sandbox Code Playgroud)
因此,下次在代码中向数组中添加新项时,如果没有另外明确设置,则元素将始终以其默认值存在.这样做可能是一个很好的想法,以及设置required你总是想要的其他领域,比如"id".