Myślę, że najlepszym sposobem, aby to zrobić, jak wspomniano tutaj, jest mongod 3.4.4+, ale bez użycia $unwind
operatora i tylko dwóch etapów w przygotowaniu. Zamiast tego możemy użyć operatorów $mergeObjects
i $objectToArray
.
Na $group
etapie używamy $mergeObjects
operatora, aby zwrócić pojedynczy dokument, w którym klucz / wartość pochodzą ze wszystkich dokumentów w kolekcji.
Potem przychodzi miejsce, w $project
którym korzystamy $map
i zwracamy $objectToArray
klucze.
let allTopLevelKeys = [
{
"$group": {
"_id": null,
"array": {
"$mergeObjects": "$$ROOT"
}
}
},
{
"$project": {
"keys": {
"$map": {
"input": { "$objectToArray": "$array" },
"in": "$$this.k"
}
}
}
}
];
Teraz, jeśli mamy zagnieżdżone dokumenty i chcemy również uzyskać klucze, jest to wykonalne. Dla uproszczenia rozważmy dokument z prostym osadzonym dokumentem, który wygląda następująco:
{field1: {field2: "abc"}, field3: "def"}
{field1: {field3: "abc"}, field4: "def"}
Poniższy potok daje wszystkie klucze (pole1, pole2, pole3, pole4).
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"
}
}
]
}
}
}
]
Przy odrobinie wysiłku możemy uzyskać klucz do całego dokumentu podrzędnego w polu tablicy, w której elementy również są obiektami.