我认为here 提到的最佳方法是在 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"
}
}
]
}
}
}
]
稍加努力,我们就可以在元素也是对象的数组字段中获取所有子文档的键。