获取嵌套 object 的所有不同键

Get all distinct keys of a nested object

我的 collection 中有以下数据:

[
    {
        _id: "2313123123",
        metadata: {
            path: "...",
            value: "...",
            name: "..."
        }
    },
    {
        _id: "2313123123",
        metadata: {
            path: "...",
            name: "...",
            origin: "...",
        }
    },
    {
        _id: "2313123123",
        metadata: {
            path: "...",
            source: "..."
        }
    },
]

我想从我的文档中检索字段 metadata 的所有不同键名。 我想检索 ["path", "value", "name", "origin", "source"].

如何查询? distinct 方法是否可行,还是我需要使用 aggregate?

您必须为此使用聚合,遗憾的是,由于您的需求的性质,这将是一个非常“昂贵”的执行管道。无法避免遍历整个集合并将唯一键添加到数组。

我们将使用 $objectToArraymetadata 变成一个数组,然后 $unwind 它,最后使用 $group 我们可以保存所有唯一值。

db.collection.aggregate([
  {
    $project: {
      keys: {
        $map: {
          input: {
            "$objectToArray": "$metadata"
          },
          in: "$$this.k"
        }
      }
    }
  },
  {
    $unwind: "$keys"
  },
  {
    $group: {
      _id: null,
      keys: {
        "$addToSet": "$keys"
      }
    }
  }
])

Mongo Playground

db.collection.aggregate([
       {
         $addFields: {
             metadata: {
                $objectToArray: "$metadata"
             }
          }
       },
      {
         $unwind: "$metadata"
      },
      {
         $group: {
            _id: "distinct",
            dist: {
               $addToSet: "$metadata.k"
            }
         }
      }
  ])

解释:

  1. 将元数据对象转换为元数据数组,将键作为 k 键中的值。
  2. 展开 k 个键和 v 个值的元数据数组
  3. 使用 addToSet 分组以仅提取最终结果中不同的 k 个值。

playground

帮助 javascript 来自 mongo shell 选项的在线人员:

 db.collection.find({},{metadata:1,_id:0}).forEach( function(doc) { for (key in doc.metadata) s.push(key); } );uni = Array.from(new Set(s));printjson(uni);
 ["path","name","origin","source","value"]