MongoDB: 如何计算每个不同值出现的次数?

3

我有一组文档,包含了不同物品的反馈列表。它看起来像这样:

{
  {
    item: "item_1"
    rating: "neutral"
    comment: "some comment"
  },
  {
    item: "item_2"
    rating: "good"
    comment: "some comment"
  },
  {
    item: "item_1"
    rating: "good"
    comment: "some comment"
  },
  {
    item: "item_1"
    rating: "bad"
    comment: "some comment"
  },
  {
    item: "item_3"
    rating: "good"
    comment: "some comment"
  },
}

我希望找到一种方法来确定每个项目获得了多少不同的评级。
因此,输出应该类似于这样:
{
  {
    item: "item_1"
    good: 12
    neutral: 10
    bad: 67
  },
  {
    item: "item_2"
    good: 2
    neutral: 45
    bad: 8
  },
  {
    item: "item_3"
    good: 1
    neutral: 31
    bad: 10
  }

}

这是我所做的:

db.collection(collectionName).aggregate(
          [
             {
               $group:
                 {
                   _id: "$item",
                   good_count: {$sum: {$eq: ["$rating",  "Good"]}},
                   neutral_count:{$sum: {$eq: ["$rating",  "Neutral"]}},
                   bad_count:{$sum: {$eq: ["$rating",  "Bad"]}},
                 }
             }
           ]
)

输出格式看起来没问题,但计数始终为0。

我想知道通过查看相同字段的不同值来将事物总结起来的正确方法是什么?

谢谢!

1个回答

1

你非常接近了,但是$eq只返回一个true/false值,所以要将其转换为数字,需要使用$cond

db.collection(collectionName).aggregate([
  { "$group" : {
       "_id": "$item",
       "good_count": { 
           "$sum": { 
               "$cond": [ { "$eq": [ "$rating",  "good" ] }, 1, 0] 
           }
       },
       "neutral_count":{
           "$sum": { 
               "$cond": [ { "$eq": [ "$rating", "neutral" ] }, 1, 0 ]
            }
       },
       "bad_count": { 
           "$sum": { 
               "$cond": [ { "$eq": [ "$rating",  "bad" ] }, 1, 0 ]
           }
       }
  }}
])

作为“三元”运算符,$cond 接受一个逻辑条件作为第一个参数(如果),然后返回第二个参数,其中评估结果为 true(则)或第三个参数,其中评估结果为 false(否则)。这将使得 true/false 返回分别成为 10,以输入到 $sum 中。
此外,请注意对于 $eq,大小写敏感。如果您的情况不同,则可能需要在表达式中使用 $toLower
               "$cond": [ { "$eq": [ { "$toLower": "$rating" },  "bad" ] }, 1, 0 ]

稍有不同的是,以下聚合通常对不同可能的值更加灵活,并且在性能方面比条件求和更加出色:

db.collection(collectionName).aggregate([
    { "$group": {
        "_id": { 
            "item": "$item",
            "rating": { "$toLower": "$rating" }
        },
        "count": { "$sum": 1 }
    }},
    { "$group": {
        "_id": "$_id.item",
        "results": {
            "$push": {
                "rating": "$_id.rating",
                "count": "$count"
            }
        }
    }}
])

那将会产生以下输出:
{
    "_id": "item_1"
    "results":[
        { "rating": "good", "count": 12 },
        { "rating": "neutral", "count": 10 }
        { "rating": "bad", "count": 67 }
    ]
}

这些信息都是相同的,但您不必显式匹配值,这种方式执行速度更快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接