【问题标题】:Create an object to already existing collection为已经存在的集合创建一个对象
【发布时间】:2023-01-12 04:41:31
【问题描述】:

我有一个具有此文档结构的集合“product_reviews”


{
  _id: 'B000000OE4',
  'product/title': 'Working Class Hero',
  'product/price': '16.99',
  reviews: [
    {
      'review/userId': 'unknown',
      'review/profileName': 'unknown',
      'review/helpfulness': '2/3',
      'review/score': '4.0',
      'review/time': '27/05/1999/00:00:00',
      'review/summary': 'Worth it for one song',
      'review/text': "I really like Joan Baez'..."
    },
    {
      'review/userId': 'A1W0RKM6J6J73L',
      'review/profileName': 'Aaron Woodin (purchagent@aol.com)',
      'review/helpfulness': '1/1',
      'review/score': '3.0',
      'review/time': '09/02/1999/00:00:00',
      'review/summary': 'The critical lambasting on the Amazon Page Missed one thing.',
      'review/text': "They forgot to mention Mary Chapin..."
    }, 
    ...
  ]
}

我的目标是为具有以下结构的每个产品添加对象(每个产品都有唯一的_id):

{
    avgReviewScore: 4.5
    reviewsCount: 105
    reviewScoreDistrib: {
        1: 15
        2:  0
        3: 30
        4: 40
        5: 20
    }
}

我尝试了许多聚合管道,但找不到解决方案。

【问题讨论】:

    标签: database mongodb mongodb-query aggregation


    【解决方案1】:

    你可以试试这段代码:

    db.product_reviews.aggregate([{
        $unwind: "$reviews"
      },
      {
        $group: {
          _id: "$_id",
          avgReviewScore: {
            $avg: "$reviews.review/score"
          },
          reviewsCount: {
            $sum: 1
          },
          scores: {
            $push: "$reviews.review/score"
          }
        }
      },
      {
        $project: {
          avgReviewScore: 1,
          reviewsCount: 1,
          reviewScoreDistrib: {
            $arrayToObject: {
              $map: {
                input: [1, 2, 3, 4, 5],
                as: "num",
                in: {
                  k: {$toString: "$$num"},
                  v: {
                    $size: {
                      $filter: {
                        input: "$scores",
                        as: "s",
                        cond: {
                          $eq: ["$$s", "$$num"]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      {
        $merge: {
          into: "product_reviews",
          on: "_id"
        }
      }
    ])

    如果你有任何问题,你可以问

    【讨论】:

    • "errmsg" : "PlanExecutor error during aggregation :: caused by :: $arrayToObject 需要一个带有键 'k' 和 'v' 的对象,其中 'k' 的值必须是字符串类型。找到的类型:double"。这是否意味着我需要转换我收藏中评论/分数的数据类型?
    • 我根据您的文档结构 (product_reviews) 进行查询
    • 我设法通过在第 k 行添加 $toString 来解决这个问题:{ $toString: "$$num" }。但是avgReviewScore和reviewScoreDistrib有问题。所有 avgReviewScore 字段都是空的,也是 reviewScoreDistrib。 reviewsCount 工作正常。
    【解决方案2】:

    无需再次 $unwind$group。你可以使用一个简单的updateMany

    db.collection.updateMany({},
      [
      {$set: {
          reviewsData: {$map: {
              input: "$reviews.review/score",
              in: {$toDouble: "$$this"}
          }}
      }},
      {$set: {
          reviewScoreDistrib: {
            $arrayToObject: {$map: {
                input: {$range: [1, 6]},
                as: "num",
                in: {
                  k: {$toString: "$$num"},
                  v: {$size: {$filter: {
                        input: "$reviewsData",
                        cond: {$eq: ["$$this", "$$num"]}
                  }}}
                }
            }}
          },
          avgReviewScore: {$avg: "$reviewsData"},
          reviewsCount: {$size: "$reviewsData"}
      }}
    ])
    

    查看它在playground example 上的工作原理

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-22
      • 2023-04-05
      • 2011-12-30
      • 2017-01-21
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多