【问题标题】:MongoDB get distinct elements from array WITH count of occurrences of each elementMongoDB从数组中获取不同的元素,每个元素的出现次数
【发布时间】:2018-09-20 08:12:31
【问题描述】:

我的收藏中有以下文件。每个文档都包含推文的文本和从推文中挑选出来的一组实体(使用 AWS Comprehend):

{
"text" : "some tweet by John Smith in New York about Stack Overflow",
"entities" : [
    {
        "Type" : "ORGANIZATION",
        "Text" : "stack overflow"
    },
    {
        "Type" : "LOCATION",
        "Text" : "new york"
    },
    {
        "Type" : "PERSON",
        "Text" : "john smith"
    }
  ]
},
{
    "text" : "another tweet by John Smith but this one from California and about Google",
    "entities" : [
    {
        "Type" : "ORGANIZATION",
        "Text" : "google"
    },
    {
        "Type" : "LOCATION",
        "Text" : "california"
    },
    {
        "Type" : "PERSON",
        "Text" : "john smith"
    }
  ]
}

我想获得一个不同的entities.Text 列表,按entities.Type 分组,每个entities.Text 的出现次数如下:

{ "_id" : "ORGANIZATION", "values" : [ {text:"stack overflow",count:1},{text:"google",count:1} ] }
{ "_id" : "LOCATION", "values" : [ {text:"new york",count:1},{text:"california",count:1} ] }
{ "_id" : "PERSON", "values" : [ {text:"john smith",count:2} ] }

我可以按entities.Type 分组,并使用此查询将所有entities.Text 放入一个数组中:

db.collection.aggregate([
{
    $unwind: '$entities'
}, 
{
    $group: {
        _id: '$entities.Type',
        values: {
            $push: '$entities.Text'
    }
}
}])

这会导致此输出包含重复值且无计数。

{ "_id" : "ORGANIZATION", "values" : [ "stack overflow", "google" ] }
{ "_id" : "LOCATION", "values" : [ "new york", "california" ] }
{ "_id" : "PERSON", "values" : [ "john smith", "john smith" ] }

我开始使用$project 作为聚合的最后一步,并使用javascript 函数添加计算字段valuesMap。但后来我意识到你不能在聚合管道中编写 javascript。

我的下一步将是使用纯 javascript 处理 mongoDB 输出,但我希望(为了学习)使用 mongoDB 查询来完成这一切。

谢谢!

【问题讨论】:

  • 您需要使用addToSet 而不是$push 将不同的元素添加到数组中。检查下面的答案。
  • @RahulRaj 抱歉,应该提到,我确实尝试过。这会给我不同的元素,但是......然后我将失去计算每个元素的出现次数的能力。
  • 好的,现在删除我的答案,因为 Veeram 的答案是正确的。

标签: mongodb group-by aggregation-framework


【解决方案1】:
db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $unwind: {
                path: '$entities'
            }
        },

        // Stage 2
        {
            $group: {
                _id: {
                    Text: '$entities.Text'
                },
                count: {
                    $sum: 1
                },
                Type: {
                    $addToSet: '$entities.Type'
                }
            }
        },

        // Stage 3
        {
            $group: {
                _id: {
                    Type: '$Type'
                },
                values: {
                    $addToSet: {
                        text: '$_id.Text',
                        count: '$count'
                    }
                }
            }
        },

        // Stage 4
        {
            $project: {
                values: 1,
                _id: {
                    $arrayElemAt: ['$_id.Type', 0]
                }
            }
        }

    ]


);

【讨论】:

    【解决方案2】:

    您可以尝试以下查询。您需要一个额外的$group 来推送计数和文本。

    db.collection.aggregate(
    [
      {"$unwind":"$entities"},
      {"$group":{
        "_id":{"type":"$entities.Type","text":"$entities.Text"},
        "count":{"$sum":1}
      }},
      {"$group":{
        "_id":"$_id.type",
        "values":{"$push":{"text":"$_id.text","count":"$count"}}
      }}
    ])
    

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 2019-09-20
      • 2010-11-06
      • 2019-04-29
      相关资源
      最近更新 更多