Với MongoDB 3.4.4, sử dụng khung tổng hợp để truy vấn tài liệu. Điều này có thể thực hiện được với $objectToArray
toán tử cho phép bạn ánh xạ các khóa trong trường được xử lý thành một mảng các cặp khóa / giá trị. Danh sách sẽ dễ dàng lọc và lấy (các) khóa phù hợp với bất kỳ điều kiện nào bạn có.
Trong ví dụ sau, đường dẫn tổng hợp bao gồm một trường bổ sung chứa (các) khóa phù hợp với điều kiện có giá trị false ở trên, vì vậy lý tưởng nhất nó sẽ là một mảng:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
cái nào mang lại
{
"_id" : ObjectId("5501b1648ef0b4eccc41814e"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
},
"notProcessed" : [
"original"
]
}
Giải thích
Bắt đầu với biểu thức lồng nhau
{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
đầu vào cho $filter
operator { "$objectToArray": "$processed" }
sẽ chuyển đổi các khóa trong processed
chìa khóa cho mảng này:
[
{
"k" : "320",
"v" : true
},
{
"k" : "480",
"v" : true
},
{
"k" : "540",
"v" : true
},
{
"k" : "720",
"v" : true
},
{
"k" : "800",
"v" : true
},
{
"k" : "1080",
"v" : true
},
{
"k" : "original",
"v" : false
},
{
"k" : "iPhone",
"v" : true
}
]
và $filter
sẽ lọc mảng ở trên để chỉ có các phần tử đối tượng có v
thuộc tính NOT
true
:
[
{
"k" : "original",
"v" : false
}
]
$map
sau đó sẽ trả về một mảng được ánh xạ chỉ với các giá trị
[ { "k" : "original", "v" : false } ] => [ "original" ]
vì vậy bạn kết thúc chỉ với
[ "original" ]
kết quả là.
Với các phiên bản MongoDB cũ hơn, sẽ khá khó khăn để đưa ra các truy vấn đối với các khóa động. Xem xét sửa đổi giản đồ của bạn để tuân theo mô hình tài liệu này, dễ truy vấn hơn:
// this operation changes the schema
var processed = [];
db.collection.find().forEach( function(doc) {
for(key in doc.processed) {
if(doc.processed.hasOwnProperty(key)) {
var item = { key: key, value: doc.processed[key] }
processed.push(item);
}
}
doc.processed = processed;
db.collection.save(doc);
});
// modified schema
{
"link": "xxxxx.jpg"
"_id": ObjectId("5501b1648ef0b4eccc41814e"),
"processed": [
{ "key": "320", "value": true },
{ "key": "480", "value": true },
{ "key": "540", "value": true },
{ "key": "720", "value": true },
{ "key": "800", "value": true },
{ "key": "1080", "value": true },
{ "key": "original", "value": false },
{ "key": "iPhone", "value": true }
]
}
Truy vấn tìm kiếm của bạn sẽ đơn giản là
db.collection.find({"processed.value": false});
hoặc sử dụng $map
và $filter
để trả lại các khóa có false
giá trị như
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])