ผมคิดว่าวิธีที่ดีที่สุดทำเช่นนี้เป็นที่กล่าวถึงที่นี่อยู่ใน mongod 3.4.4+ แต่โดยไม่ต้องใช้$unwind
ผู้ประกอบการและใช้เพียงสองขั้นตอนในท่อ แต่เราสามารถใช้ตัวดำเนินการ$mergeObjects
และ$objectToArray
ใน$group
ขั้นตอนนี้เราใช้$mergeObjects
โอเปอเรเตอร์เพื่อส่งคืนเอกสารเดียวโดยที่คีย์ / ค่ามาจากเอกสารทั้งหมดในคอลเล็กชัน
จากนั้นมาถึงจุด$project
ที่เราใช้$map
และ$objectToArray
เพื่อส่งคืนกุญแจ
let allTopLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$map": {
"input": { "$objectToArray": "$array" },
"in": "$$this.k"
}
}
}
}
];
ตอนนี้ถ้าเรามีเอกสารซ้อนกันและต้องการได้รับกุญแจเช่นกันสิ่งนี้สามารถทำได้ เพื่อความง่ายให้พิจารณาเอกสารที่มีเอกสารแบบฝังที่มีลักษณะดังนี้
{field1: {field2: "abc"}, field3: "def"}
{field1: {field3: "abc"}, field4: "def"}
ไพพ์ไลน์ต่อไปนี้จะให้คีย์ทั้งหมด (field1, field2, field3, field4)
let allFistSecondLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$setUnion": [
{
"$map": {
"input": {
"$reduce": {
"input": {
"$map": {
"input": {
"$objectToArray": "$array"
},
"in": {
"$cond": [
{
"$eq": [
{
"$type": "$$this.v"
},
"object"
]
},
{
"$objectToArray": "$$this.v"
},
[
"$$this"
]
]
}
}
},
"initialValue": [
],
"in": {
"$concatArrays": [
"$$this",
"$$value"
]
}
}
},
"in": "$$this.k"
}
}
]
}
}
}
]
ด้วยความพยายามเพียงเล็กน้อยเราสามารถรับกุญแจสำหรับเอกสารย่อยทั้งหมดในเขตข้อมูลอาร์เรย์ที่องค์ประกอบเป็นวัตถุได้เช่นกัน