Truy vấn
-
nó là một bản cập nhật tổng hợp ngay cả khi đường ống không cho phép chúng tôi sử dụng các giai đoạn như tra cứu nhóm, v.v. mà ở đây được sử dụng. (bạn có thể sử dụng
$out
và thay thế bộ sưu tập sau hoặc$merge
để thay thế tài liệu (tương tự như cập nhật)) -
bản đồ đầu tiên
- đối với mỗi đặc điểm (thành viên tài liệu của các đặc điểm), nó làm cho nó thành mảng
[["trait_type": "type"] ["value": "Male"] ["display_type": null] ...]
- giảm trên mảng đó để cấu trúc từ chúng chỉ 1 tài liệu
{"type" "type","value" :"Male"}
(cũng viết thường và "_")
- đối với mỗi đặc điểm (thành viên tài liệu của các đặc điểm), nó làm cho nó thành mảng
-
Bây giờ các đặc điểm của nó giống như
"traits": [ { "type": "type", "value": "Male" }, { "type": "accessory", "value": "Mohawk" }, { "type": "accessory", "value": "Earring" }, { "type": "accessory", "value": "Frown" } ]
-
tra cứu với bộ sưu tập giả
[{}]
(chúng tôi làm điều đó để tạo một nhóm bên trong mảng đó) nó giống như một thủ thuật cho phép chúng tôi sử dụng các toán tử giai đoạn bên trong 1 tài liệu- tìm kiếm các lần mở và nhóm theo loại đường ống dẫn
"traits": [ { "values": [ "Mohawk", "Earring", "Frown" ], "type": "accessory" }, { "values": [ "Male" ], "type": "type" } ]
- sau đó, nó là một gốc thay thế để lấy giá trị của kiểu, đặt nó thành tên trường và các giá trị dưới dạng giá trị
(if size=1 removes the array)
-
Sau khi tra cứu, chúng tôi có
"traits": [ { "accessory": [ "Mohawk", "Earring", "Frown" ] }, { "type": "Male" } ]
-
vì vậy tất cả những gì chúng ta phải làm là giảm bớt các đặc điểm đó và hợp nhất các đối tượng (các khóa luôn là duy nhất vì chúng ta đã nhóm chúng lại)
-
và chúng tôi nhận được kết quả mong đợi (ít nhất tôi nghĩ nó ổn)
db.collection.aggregate([
{
"$set": {
"traits": {
"$map": {
"input": "$traits",
"as": "t",
"in": {
"$reduce": {
"input": {
"$map": {
"input": {
"$objectToArray": "$$t"
},
"as": "m",
"in": [
"$$m.k",
"$$m.v"
]
}
},
"initialValue": {},
"in": {
"$let": {
"vars": {
"type_value": "$$value",
"ta": "$$this"
},
"in": {
"$let": {
"vars": {
"key": {
"$arrayElemAt": [
"$$ta",
0
]
},
"value": {
"$arrayElemAt": [
"$$ta",
1
]
}
},
"in": {
"$switch": {
"branches": [
{
"case": {
"$eq": [
"$$key",
"value"
]
},
"then": {
"$mergeObjects": [
"$$type_value",
{
"value": "$$value"
}
]
}
},
{
"case": {
"$eq": [
"$$key",
"trait_type"
]
},
"then": {
"$mergeObjects": [
"$$type_value",
{
"type": {
"$replaceAll": {
"input": {
"$toLower": "$$value"
},
"find": " ",
"replacement": "_"
}
}
}
]
}
}
],
"default": "$$type_value"
}
}
}
}
}
}
}
}
}
}
}
},
{
"$lookup": {
"from": "dummy",
"let": {
"traits": "$traits"
},
"pipeline": [
{
"$set": {
"traits": "$$traits"
}
},
{
"$unwind": {
"path": "$traits"
}
},
{
"$replaceRoot": {
"newRoot": "$traits"
}
},
{
"$group": {
"_id": "$type",
"values": {
"$push": "$value"
}
}
},
{
"$set": {
"type": "$_id"
}
},
{
"$project": {
"_id": 0
}
},
{
"$replaceRoot": {
"newRoot": {
"$cond": [
{
"$eq": [
{
"$size": "$values"
},
1
]
},
{
"$arrayToObject": {
"$let": {
"vars": {
"pair": [
[
"$type",
{
"$arrayElemAt": [
"$values",
0
]
}
]
]
},
"in": "$$pair"
}
}
},
{
"$arrayToObject": {
"$let": {
"vars": {
"pair": [
[
"$type",
"$values"
]
]
},
"in": "$$pair"
}
}
}
]
}
}
}
],
"as": "traits"
}
},
{
"$set": {
"traits": {
"$mergeObjects": "$traits"
}
}
}
])