【问题标题】:Multiple Grouping in Mongo AggregationMongodb聚合中的多个分组
【发布时间】:2017-04-08 08:32:40
【问题描述】:

我的 mongo db 数据是这样的

{ "_id" : ObjectId("58e879052b614ce778fb7af2"), "email" : "abc@gmail.com", "phone" : 1234 }
{ "_id" : ObjectId("58e879052b614ce778fb7af3"), "email" : "efg@gmail.com", "phone" : 2346 }
{ "_id" : ObjectId("58e879052b614ce778fb7af4"), "email" : "abc@gmail.com", "phone" : 7896 }
{ "_id" : ObjectId("58e879052b614ce778fb7af5"), "phone" : 5789, "email" : "abc@gmail.com" }
{ "_id" : ObjectId("58e879052b614ce778fb7af6"), "phone" : 7896, "email" : "hij@gmail.com" }
{ "_id" : ObjectId("58e879052b614ce778fb7af7"), "phone" : 3492, "email" : "lmn@gmail.com" }
{ "_id" : ObjectId("58e879052b614ce778fb7af8"), "phone" : 5555, "email" : "cdf@gmail.com" }
{ "_id" : ObjectId("58e87ea96774f88e108b4567"), "phone" : 5789, "email" : "abc@gmail.com" }
{ "_id" : ObjectId("58e880db6774f8130f8b4567"), "phone" : 5789, "email" : "" }
{ "_id" : ObjectId("58e880e56774f81f108b4567"), "phone" : 1234, "email" : "" }
{ "_id" : ObjectId("58e880f96774f83b108b4567"), "phone" : 9846, "email" : "" }
{ "_id" : ObjectId("58e881016774f83b108b4568"), "phone" : 1012, "email" : "" }
{ "_id" : ObjectId("58e8812a6774f8c0108b4567"), "phone" : 1258 }
{ "_id" : ObjectId("58e881496774f80e108b4567"), "phone" : 1012, "email" : "" }

我想先根据电子邮件和电话进行分组。

{ "_id" : ObjectId("58e879052b614ce778fb7af2"), "email" : "abc@gmail.com", "phone" : 1234 }
{ "_id" : ObjectId("58e879052b614ce778fb7af3"), "email" : "efg@gmail.com", "phone" : 2346 }
{ "_id" : ObjectId("58e879052b614ce778fb7af6"), "phone" : 7896, "email" : "hij@gmail.com" }
{ "_id" : ObjectId("58e879052b614ce778fb7af7"), "phone" : 3492, "email" : "lmn@gmail.com" }
{ "_id" : ObjectId("58e879052b614ce778fb7af8"), "phone" : 5555, "email" : "cdf@gmail.com" }
{ "_id" : ObjectId("58e880f96774f83b108b4567"), "phone" : 9846, "email" : "" }
{ "_id" : ObjectId("58e881016774f83b108b4568"), "phone" : 1012, "email" : "" }
{ "_id" : ObjectId("58e8812a6774f8c0108b4567"), "phone" : 1258 }

我想要除具有相应电话号码的空值之外的所有电子邮件 ID。还需要与群组电子邮件具有不同电子邮件 ID 的电话号码。具有空电子邮件 ID 或没有密钥电子邮件的电话号码也应包含在输出中。

谢谢你。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    您需要$group$first 聚合命令,通过电子邮件和电话进行分组,您必须使用$cond 和最后一个$project 进行清理。

    没有重复抑制的第一个解决方案

    db.data.aggregate([       {$group: {_id: {$cond: {if: {"$eq": ['$email', '']}, else: {email: '$email'}, then: {phone: '$phone', email: '$email'}}}, firstId: {$first: '$_id'}, phone: {$first: '$phone'}}},        {$project: {_id: '$firstId', phone: '$phone', email: '$_id.email'}}     ])
    { "_id" : ObjectId("58e880f96774f83b108b4567"), "phone" : 9846, "email" : "" }
    { "_id" : ObjectId("58e881016774f83b108b4568"), "phone" : 1012, "email" : "" }
    { "_id" : ObjectId("58e880e56774f81f108b4567"), "phone" : 1234, "email" : "" }
    { "_id" : ObjectId("58e880db6774f8130f8b4567"), "phone" : 5789, "email" : "" }
    { "_id" : ObjectId("58e879052b614ce778fb7af8"), "phone" : 5555, "email" : "cdf@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af6"), "phone" : 7896, "email" : "hij@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af7"), "phone" : 3492, "email" : "lmn@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af3"), "phone" : 2346, "email" : "efg@gmail.com" }
    { "_id" : ObjectId("58e8812a6774f8c0108b4567"), "phone" : 1258 }
    { "_id" : ObjectId("58e879052b614ce778fb7af2"), "phone" : 1234, "email" : "abc@gmail.com" }
    

    具有重复抑制的第二个解决方案

    db.data.aggregate([
      {$group: {_id: '$phone', emails: {$addToSet: {email: '$email', _id: '$_id'}}, countNonBlank: {$sum: {$cond: [{$eq: ['$email', '']}, 0,  1]}}}}, {$unwind: {path: '$emails', preserveNullAndEmptyArrays: true}}, 
      {$match: {$or: [{'emails.email': {$ne: ''}}, {"countNonBlank": {$lt: 1}, "emails.email": {$eq: ''}}]}}, 
      {$project: {phone: '$_id', email: '$emails.email', _id: '$emails._id'}}, 
      {$group: {_id: {email: '$email', phone: '$phone'}, firstId: {$first: '$_id'}}}, 
      {$project: {_id: '$firstId', phone: '$_id.phone', email: '$_id.email'}}, 
      {$group: {_id: {$cond: {if: {"$eq": ['$email', '']}, else: {email: '$email'}, then: {phone: '$phone', email: '$email'}}}, firstId: {$first: '$_id'}, phone: {$first: '$phone'}}},        
      {$project: {_id: '$firstId', phone: '$phone', email: '$_id.email'}}     
    ])
    { "_id" : ObjectId("58e881496774f80e108b4567"), "phone" : 1012, "email" : "" }
    { "_id" : ObjectId("58e880f96774f83b108b4567"), "phone" : 9846, "email" : "" }
    { "_id" : ObjectId("58e879052b614ce778fb7af3"), "phone" : 2346, "email" : "efg@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af7"), "phone" : 3492, "email" : "lmn@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af6"), "phone" : 7896, "email" : "hij@gmail.com" }
    { "_id" : ObjectId("58e879052b614ce778fb7af8"), "phone" : 5555, "email" : "cdf@gmail.com" }
    { "_id" : ObjectId("58e8812a6774f8c0108b4567"), "phone" : 1258 }
    { "_id" : ObjectId("58e879052b614ce778fb7af2"), "phone" : 1234, "email" : "abc@gmail.com" }
    

    【讨论】:

    • 这似乎有效。但我想要 { "_id" : ObjectId("58e880f96774f83b108b4567"), "phone" : 9846, "email" : "" } { "_id" : ObjectId("58e881016774f83b108b4568"), "phone" : 1012, "email" : "" } 在我的输出中也有记录。
    • 您好 Julien TASSIN,您能再看看这个问题吗?我增加了一些要求。谢谢你:)
    • 你能看一下语法吗?它显示了一些意外的令牌错误。再次抱歉给您带来麻烦。
    • 感谢您提供更正的语法 :) 抱歉,还有一个条件。由于电话号码 1234 和 5789 是电子邮件 ID abc@gmail.com 的一部分,因此无需针对空电子邮件值将其包含在输出中。你能不能也检查一下。
    • 对不起,我在第二个解决方案中再次遇到一些错误,重复抑制为“errmsg”:“异常:$unwind 字段路径必须指定为字符串”,“代码”:15981。不知道为什么。
    猜你喜欢
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 2023-01-17
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多