Mongodb 在聚合中对多个值进行分组

Mongodb 在聚合中对多个值进行分组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我想将集合的“所有”字段分组为“唯一总计”。假设有这样的集合: id country state operator 121 IN HR AIRTEL 212 IN MH AIRTEL 213 US LA AT&T 214 UK JK VODAFONE 输出应如下所示: id country state operator 121 IN HR AIRTEL

我想将集合的“所有”字段分组为“唯一总计”。假设有这样的集合:

 id  country state operator
 121  IN       HR    AIRTEL
 212  IN       MH    AIRTEL
 213  US       LA    AT&T
 214  UK       JK    VODAFONE        
输出应如下所示:

 id  country state operator
 121  IN       HR    AIRTEL
 212  IN       MH    AIRTEL
 213  US       LA    AT&T
 214  UK       JK    VODAFONE        
{
“国家”:{“在”:2,“美国”:1,“英国”:1},
“州”:{“HR”:1,“MH”:1,“LA”:1,“JK”:1},
“接线员”:{“AIRTEL”:2,“AT&T”:1,“沃达丰”:1}
}

我正在尝试使用mongo聚合框架,但无法真正思考如何做到这一点?

我在下面的代码中找到了一些类似于使用聚合检查的输出

db.collectionName.aggregate({
  "$group": {
    "_id": null,
    "countryOfIN": {
      "$sum": {
        "$cond": [{
          $eq: ["$country", "IN"]
        }, 1, 0]
      }
    },
    "countryOfUK": {
      "$sum": {
        "$cond": [{
          $eq: ["$country", "UK"]
        }, 1, 0]
      }
    },
    "countryOfUS": {
      "$sum": {
        "$cond": [{
          $eq: ["$country", "US"]
        }, 1, 0]
      }
    },
    "stateOfHR": {
      "$sum": {
        "$cond": [{
          $eq: ["$state", "HR"]
        }, 1, 0]
      }
    },
    "stateOfMH": {
      "$sum": {
        "$cond": [{
          $eq: ["$state", "MH"]
        }, 1, 0]
      }
    },
    "stateOfLA": {
      "$sum": {
        "$cond": [{
          $eq: ["$state", "LA"]
        }, 1, 0]
      }
    },
    "stateOfJK": {
      "$sum": {
        "$cond": [{
          $eq: ["$state", "JK"]
        }, 1, 0]
      }
    },
    "operatorOfAIRTEL": {
      "$sum": {
        "$cond": [{
          $eq: ["$operator", "AIRTEL"]
        }, 1, 0]
      }
    },
    "operatorOfAT&T": {
      "$sum": {
        "$cond": [{
          $eq: ["$operator", "AT&T"]
        }, 1, 0]
      }
    },
    "operatorOfVODAFONE": {
      "$sum": {
        "$cond": [{
          $eq: ["$operator", "VODAFONE"]
        }, 1, 0]
      }
    }
  }
}, {
  "$group": {
    "_id": null,
    "country": {
      "$push": {
        "IN": "$countryOfIN",
        "UK": "$countryOfUK",
        "US": "$countryOfUS"
      }
    },
    "STATE": {
      "$push": {
        "HR": "$stateOfHR",
        "MH": "$stateOfMH",
        "LA": "$stateOfLA",
        "JK": "$stateOfJK"
      }
    },
    "operator": {
      "$push": {
        "AIRTEL": "$operatorOfAIRTEL",
        "AT&T": "$operatorOfAT&T",
        "VODAFONE": "$operatorOfVODAFONE"
      }
    }
  }
}, {
  "$project": {
    "_id": 0,
    "country": 1,
    "STATE": 1,
    "operator": 1
  }
})

使用已创建的匹配数据组,并将它们分为第二组进行组合。

您正在寻找的输出格式并不真正适合聚合框架,因为您正在将部分数据转换为“键”名称。聚合框架不这样做,而是坚持数据库“最佳实践”,因为它不会以任何方式将“数据”转换为“键”名称

您可以使用执行mapReduce操作,以允许更灵活的操作,但由于需要使用JavaScript代码来执行操作,因此性能不佳:

db.collection.mapReduce(
函数(){
var obj={},
doc=这个;
删除单据。\u id;
Object.key(doc.forEach)函数(key){
obj[key]={};
obj[key][doc[key]]=1;
});
发射(空,obj);
},
功能(键、值){
var result={};
values.forEach(函数(值){
Object.keys(值).forEach(函数(outerKey){
Object.key(值[outerKey]).forEach(函数(innerKey){
如果(!result.hasOwnProperty(outerKey)){
结果[outerKey]={};
}
if(结果[outerKey].hasOwnProperty(innerKey)){
结果[outerKey][innerKey]+=值[outerKey][innerKey];
}否则{
结果[outerKey][innerKey]=值[outerKey][innerKey];
}
});
});
});
返回结果;
},
{“out”:{“inline”:1}
)
在适用于所有mapReduce结果的结构中:

{
“结果”:[
{
“_id”:空,
“价值”:{
“国家”:{
“IN”:2,
"美国":一,,
“英国”:1
},
“国家”:{
“人力资源”:1,
“MH”:1,
“LA”:1,
“JK”:1
},
“操作员”:{
“空中电话”:2,
“AT&T”:1,
“沃达丰”:1
}
}
}
]
}
对于聚合框架本身,它更适合生成结构更一致的聚合结果:

db.mapex.aggregate([
{“$project”:{
“国家”:1,
“国家”:1,
“操作员”:1,
“类型:{“$literal”:[“国家”、“州”、“运算符”]}
}},
{“$unwind”:“$type”},
{“$组”:{
“_id”:{
“类型”:“$type”,
“键”:{“$cond”:{
“如果”:{“$eq”:[“$type”,“country”]},
“然后”:“$country”,
“else”:{“$cond”:{
“if”:{“$eq”:[“$type”,“state”]},
“然后”:“$state”,
“else”:“$operator”
}}
}}
},
“计数”:{“$sum”:1}
}}
])
这将产生:

{u id:{“type”:“state”,“key”:“JK”},“count”:1}
{u id:{“type”:“country”,“key”:“UK”},“count”:1}
{{u id:{“type”:“country”,“key”:“US”},“count”:1}
{u id:{type:“operator”,“key:“AT&T”},“count”:1}
{u id:{“type”:“state”,“key”:“LA”},“count”:1}
{u id:{“type”:“operator”,“key”:“AIRTEL”},“count”:2}
{u id:{“type”:“state”,“key”:“MH”},“count”:1}
{u id:{type:“state”,“key:“HR”},“count”:1}
{u id:{“type”:“operator”,“key”:“VODAFONE”},“count”:1}
{u id:{“type”:“country”,“key”:“IN”},“count”:2}
但在迭代结果时,在客户机代码中进行转换相当容易:

var result={};
db.mapex.aggregate([
{“$project”:{
“国家”:1,
“国家”:1,
“操作员”:1,
“类型:{“$literal”:[“国家”、“州”、“运算符”]}
}},
{“$unwind”:“$type”},
{“$组”:{
“_id”:{
“类型”:“$type”,
“键”:{“$cond”:{
“如果”:{“$eq”:[“$type”,“country”]},
“然后”:“$country”,
“else”:{“$cond”:{
“if”:{“$eq”:[“$type”,“state”]},
“然后”:“$state”,
“else”:“$operator”
}}
}}
},
“计数”:{“$sum”:1}
}}
]).forEach(功能(文档){
如果(!result.hasOwnProperty(doc.\u id.type))
结果[doc.\u id.type]={};
结果[doc.\u id.type][doc.\u id.key]=doc.count;
})
在“结果”中给出了最终结构:

{
“国家”:{
“JK”:1,
“LA”:1,
“MH”:1,
“人力资源”:1
},
“国家”:{
“英国”:1,
"美国":一,,
“IN”:2
},
“操作员”:{
“AT&T”:1,
“空中电话”:2,
“沃达丰”:1
}
}

不可能使用
聚合框架
。你需要使用
Map Reduce
@BatScream你能给出一些例子或链接来参考吗?-这应该是一个非常简单和有效的起点。