MongoDB:如何对$ project字段进行分组?

时间:2018-03-11 13:51:29

标签: mongodb

模式

单个文档如下所示:

{
  row: [
    { identifier: 'a', value: '2000-01-01' },
    { identifier: 'b', value: 5 },
    { identifier: 'c', value: 99 },
  ]
}

通缉结果

我想按年分组。更确切地说:identifier a的值应该是年份,identifier c的值应该相加。所以,结果应该是:

[
  { x: '2000', y: 105 },
  { x: '2001', y: 67 },
  { x: '2002', y: 99 }
]

方法

{
  $unwind: '$row'
}, {
  $match: {
    $or: [
      {'row.identifier': 'a'},
      {'row.identifier': 'c'}
    ]
  }
}, {
  $project: {
    x: {
      $cond: {
        if: {$eq: ['$row.identifier', 'a']},
        then: '$row.value',
        else: '$$REMOVE'
      }
    },

    y: {
      $cond: {
        if: {
          $eq: ['$row.identifier', 'c']
        },
        then: '$row.value',
        else: '$$REMOVE'
      }
    }
  }
}, {
  $group: {
    _id: {
      x: { $substr : ['$x', 0, 4 ] }
    },
    y: {
      $sum: '$y'
    }
  }
}

问题

它不会返回想要的结果。我不知道如何再次x之后合并y$project。或者整个方法可能效率不高。

2 个答案:

答案 0 :(得分:2)

使用以下聚合查询。

[
  {"$unwind":"$row"},
  {"$match":{
    "$or":[
      {"row.identifier":"a"},
      {"row.identifier":"c"}
    ]
  }},
  {"$group":{
    "_id":{
      "x":{
        "$cond":[
          {"$eq":["$row.identifier","a"]},
          {"$substr":["$row.value",0,4]},
          null
        ]
      }
     },
     "y":{
        "$sum":{
          "$cond":[
            {"$eq":["$row.identifier","c"]},
            "$row.value",
            0
          ]
        }
     }
  }}
]

答案 1 :(得分:1)

我在尝试展开后尝试使用ac并使用db.stackoverflow.insert({ row: [ { identifier: 'a', value: '2001-01-01' }, { identifier: 'b', value: 5 }, { identifier: 'c', value: 100 } ] }) db.stackoverflow.find() { "_id" : ObjectId("5aa5440e3e2cfe6e23b2de47"), "row" : [ { "identifier" : "a", "value" : "2000-01-01" }, { "identifier" : "b", "value" : 5 }, { "identifier" : "c", "value" : 99 } ] } { "_id" : ObjectId("5aa544143e2cfe6e23b2de48"), "row" : [ { "identifier" : "a", "value" : "2000-01-01" }, { "identifier" : "b", "value" : 5 }, { "identifier" : "c", "value" : 1 } ] } { "_id" : ObjectId("5aa544223e2cfe6e23b2de49"), "row" : [ { "identifier" : "a", "value" : "2001-01-01" }, { "identifier" : "b", "value" : 5 }, { "identifier" : "c", "value" : 1 } ] } { "_id" : ObjectId("5aa544263e2cfe6e23b2de4a"), "row" : [ { "identifier" : "a", "value" : "2001-01-01" }, { "identifier" : "b", "value" : 5 }, { "identifier" : "c", "value" : 100 } ] } { "_id" : ObjectId("5aa545853e2cfe6e23b2de4b"), "row" : [ { "identifier" : "a", "value" : "2001-01-01" }, { "identifier" : "b", "value" : 5 }, { "identifier" : "c", "value" : 1 } ] } 过滤行,因为它已经准备好了,它会获得所需的结果。

第1步:插入一些您提供的文件:

    db.stackoverflow.aggregate([
        {$unwind: "$row"}, 
        {$match: 
            {$or: [ {"row.identifier": "a" }, {"row.identifier": "c"}]}
        },
        {
            $project: {
                yearstring: {
                    $cond: {
                        if: {$eq: ['$row.identifier', 'a']},
                        then: '$row.value',
                        else: '$$REMOVE'
                    }
                },
                valueString: {
                    $cond: {
                        if: { $eq: ['$row.identifier', 'c']},
                        then: '$row.value',
                        else: '$$REMOVE'
                    }
                }
            }
        },
        {
            $group: {
                _id: "$_id",
                "row": {
                    "$push": {
                        "year": "$yearstring",
                        "value": "$valueString"
                    }
                }      
            }
        },
        {
            $project: {
                _id: "$_id",
                year: { $arrayElemAt: [ "$row.year", 0 ] },
                value: {$arrayElemAt: ["$row.value", 0] }          
            }
        },
        {
            $project: {
                _id: 1,
                year: { $substr: [ "$year", 0, 4 ] },
                value: 1         
            }
        },
        {
            $group: {
                _id: "$year",
                y: {$sum: "$value"}
            }
        }
    ])

第2步:查看插入的所有元素

    { "_id" : "2000", "y" : 100 }
    { "_id" : "2001", "y" : 102 }

第3步:聚合逻辑,从您提供的代码中复制的过滤条件:

{{1}}

步骤4:输出上述聚合:

{{1}}

你可以减少一些阶段。希望您能获得如何获得结果的想法。

您可以在我的github repo

上获取所有代码