首页 > 解决方案 > mongodb对数组内嵌套对象的不同操作

问题描述

我的 mongodb 数据库看起来像这样。

[{
    "_id": ObjectId("5e049ebc8e935c407f78c190"),
    "2020-04-25": [
      {
        "browser": "Chrome",
        "ts": "2020-04-25 21:05"
      },
      {
        "browser": "Firefox",
        "ts": "2020-04-25 21:05"
      }
    ]
  },
  {
    "_id": ObjectId("5e049ebc8e935c407f68c190"),
    "2020-04-26": [
      {
        "browser": "Chrome",
        "ts": "2020-04-26 10:45"
      },
      {
        "browser": "Edge",
        "ts": "2020-04-26 10:45"
      },
      {
        "browser": "Firefox",
        "ts": "2020-04-26 10:46"
      }
    ]
  }]

我想找到key browser 的所有不同值

我尝试使用 distinct,但我坚持如何在数据库中的所有日期使用它。

我尝试了 $all 运算符,但发现它只能用于值而不是键。

标签: javascriptmongodb

解决方案


使用当前的数据结构,无法避免在所有数据上使用$objectToArray然后进行分组。这将使这条管道非常低效。

db.collection.aggregate([
    {
        "$addFields": {
            "newField": {
                "$objectToArray": "$$ROOT"
            }
        }
    },
    {
        "$unwind": "$newField"
    },
    {
        "$unwind": "$newField.v"
    },
    {
        "$group": {
            "_id": "$newField.v.browser"
        }
    },
    {
        "$match": {
            // this null is due to the _id field, you could also filter "newField" before unwinding instead.
            "_id": {"$ne": null}
        }
    }
]);

话虽如此,我建议您考虑重新构建数据,例如:

{
    "_id": ObjectId("5e049ebc8e935c407f68c190"),
    date: "2020-04-26",
    data: [
        {
            "browser": "Chrome",
            "ts": "2020-04-26 10:45"
        },
        {
            "browser": "Edge",
            "ts": "2020-04-26 10:45"
        },
        {
            "browser": "Firefox",
            "ts": "2020-04-26 10:46"
        }
    ]
}

现在您可以轻松实现相同的结果(以及许多其他结果),如下所示:

db.collection.distinct("data.browser")

推荐阅读