【问题标题】:MongoDB populate a field and count total 'true' values in nested boolean fields using mongooseMongoDB 使用 mongoose 填充一个字段并计算嵌套布尔字段中的总“真”值
【发布时间】:2021-04-21 18:15:23
【问题描述】:

我有两个mongo文件的结构

链接文档

{
  "_id": {
    "$oid": "6002d2d627925c4194a15a94"
  },
  "visit_count": 20,
  "password": null,
  "password_protected": false,
  "description": null,
  "analytics": [
    {
      "$oid": "6002d568e9c7d24d34413492"
    },
    {
      "$oid": "6002d612464785401824a782"
    }
  ],
  "alias": "g",
  "short_url": "https://reduced.me/g",
  "long_url": "https://google.com",
  "created": {
    "$date": "2021-01-16T11:49:42.517Z"
  },
  "__v": 2
}

分析文档

[
  {
    "_id": {
      "$oid": "6002d568e9c7d24d34413492"
    },
    "os": {
      "windows": true,
      "linux": false,
      "mac": false,
      "android": false
    },
    "browser": {
      "opera": false,
      "ie": false,
      "edge": false,
      "safari": false,
      "firefox": true,
      "chrome": false
    },
    "details": {
      "os": "Windows 10.0",
      "browser": "Edge",
      "version": "87.0.664.75",
      "platform": "Microsoft Windows",
      "source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
    },
    "__v": 0
  },
  {
    "_id": {
      "$oid": "6002d612464785401824a782"
    },
    "os": {
      "windows": true,
      "linux": false,
      "mac": false,
      "android": false
    },
    "browser": {
      "opera": false,
      "ie": false,
      "edge": true,
      "safari": false,
      "firefox": false,
      "chrome": false
    },
    "details": {
      "os": "Windows 10.0",
      "browser": "Edge",
      "version": "87.0.664.75",
      "platform": "Microsoft Windows",
      "source": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
    },
    "__v": 0
  }
]

我想要做的是,用 analytics 文档中的值填充 links 文档中的 analytics 数组,并总结 true boolean 的计数osbrowser 对象中每个字段的值。我正在寻找的输出结构是 -

{
    "_id": null,
    "visit_count": 20,
    "password_protected": false,
    "description": null,
    "alias": "g",
    "short_url": "https://reduced.me/g",
    "long_url": "https://google.com",
    "created": "2021-01-16T11:49:42.517Z",
    "analytics": {
        "os": {
            "windows": 2,
            "linux": 0,
            "mac": 0,
            "android": 0
        },
        "browser": {
            "opera": 0,
            "ie": 0,
            "edge": 1,
            "safari": 0,
            "firefox": 1,
            "chrome": 0
        }
    }
}

例如,此处windows:2 显示在整个文档中windows 的值为true 的次数。

目前我正在这样做

const analytics = await LinkModel.aggregate([
        { $match: { short_url: req.body.short_url } },

        {
            $lookup: {
                from: 'analytics',
                localField: 'analytics',
                foreignField: '_id',
                as: 'analytics',
            },
        },
        { $unwind: '$analytics' },
        {
            $group: {
                _id: null,

                visit_count: { $first: '$visit_count' },
                password_protected: { $first: '$password_protected' },
                description: { $first: '$description' },
                alias: { $first: '$alias' },
                short_url: { $first: '$short_url' },
                long_url: { $first: '$long_url' },
                created: { $first: '$created' },

                windows: {
                    $sum: { $cond: ['$analytics.os.windows', 1, 0] },
                },
                linux: {
                    $sum: { $cond: ['$analytics.os.linux', 1, 0] },
                },
                mac: {
                    $sum: { $cond: ['$analytics.os.mac', 1, 0] },
                },
                android: {
                    $sum: { $cond: ['$analytics.os.android', 1, 0] },
                },
                opera: {
                    $sum: { $cond: ['$analytics.browser.opera', 1, 0] },
                },
                ie: {
                    $sum: { $cond: ['$analytics.browser.ie', 1, 0] },
                },
                edge: {
                    $sum: { $cond: ['$analytics.browser.edge', 1, 0] },
                },
                safari: {
                    $sum: {
                        $cond: ['$analytics.browser.safari', 1, 0],
                    },
                },
                firefox: {
                    $sum: {
                        $cond: ['$analytics.browser.firefox', 1, 0],
                    },
                },
                chrome: {
                    $sum: {
                        $cond: ['$analytics.browser.chrome', 1, 0],
                    },
                },
            },
        },
    ])

这确实给出了这样的输出

[{
    "_id": null,
    "visit_count": 20,
    "password_protected": false,
    "description": null,
    "alias": "g",
    "short_url": "https://reduced.me/g",
    "long_url": "https://google.com",
    "created": "2021-01-16T11:49:42.517Z",
    "windows": 2,
    "linux": 0,
    "mac": 0,
    "android": 0,
    "opera": 0,
    "ie": 0,
    "edge": 1,
    "safari": 0,
    "firefox": 1,
    "chrome": 0
}]

它有我需要的所有数据,但结构不正确。我使用猫鼬作为 ORM。任何帮助,将不胜感激。谢谢。

【问题讨论】:

    标签: mongodb mongoose aggregation-framework nested-queries


    【解决方案1】:

    你可以使用$addFields来获得你想要的输出

    db.collection.aggregate([
      {
        $addFields: {
          "analytics": {
            "os": {
              "windows": "$windows",
              "linux": "$linux",
              "mac": "$mac",
              "android": "$android"
            },
            "browser": {
              "opera": "$opera",
              "ie": "$ie",
              "edge": "$edge",
              "safari": "$safari",
              "firefox": "$firefox",
              "chrome": "$chrome"
            }
          },
          "windows": "$$REMOVE",
          "linux": "$$REMOVE",
          "mac": "$$REMOVE",
          "android": "$$REMOVE",
          "opera": "$$REMOVE",
          "ie": "$$REMOVE",
          "edge": "$$REMOVE",
          "safari": "$$REMOVE",
          "firefox": "$$REMOVE",
          "chrome": "$$REMOVE"
        }
      }
    ])
    

    工作Mongo playground

    【讨论】:

    • EDIT-使用您提供的代码解决了它。感谢您的快速回答,但我之前尝试过 $addFields。我需要将它添加到管道或其他东西吗?或者你能用聚合+ $addFields 给出整个代码吗?
    • 您在$group 阶段之后发布了结果,对吧?之后,这样做$addFields
    • 欢迎来到stackoverflow,请看meta.stackexchange.com/a/5235/618454接受答案
    • 我将其标记为已接受的答案。还有一件事,目前我在一个数组中得到输出,里面有一个包含所有数据的对象。有什么方法可以删除外部数组并只获取文档吗?
    • 谢谢。现在我只是在将响应返回给客户端时对其进行清理。
    猜你喜欢
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 2019-10-19
    • 2021-04-19
    • 2012-01-22
    • 2017-05-21
    • 1970-01-01
    • 2018-08-25
    相关资源
    最近更新 更多