Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 从数组中聚合总计_Mongodb_Aggregation Framework - Fatal编程技术网

Mongodb 从数组中聚合总计

Mongodb 从数组中聚合总计,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我在使用MongoDb分组数据时遇到问题 我有一堆有一些进出运动的项目,我想计算一个有运动量的项目摘要,但运动计算不正确 这是我的样本数据,一个包含两支股票和一些走势的小列表 /* 1 */ { "TemplateName" : "SAALottoStagionatura", "idStock" : 31789, "idWarehouse" : 191, "StockCode" : "71529902", "Marks" : [ {

我在使用MongoDb分组数据时遇到问题

我有一堆有一些进出运动的项目,我想计算一个有运动量的项目摘要,但运动计算不正确

这是我的样本数据,一个包含两支股票和一些走势的小列表

/* 1 */
{
    "TemplateName" : "SAALottoStagionatura",
    "idStock" : 31789,
    "idWarehouse" : 191,
    "StockCode" : "71529902",   
    "Marks" : [ 
        {
            "idMark" : 20145,
            "idWarehouse" : 191,
            "idStock" : 31789,
            "ProgressivoDocumento" : 486,
            "Year" : 2016,
            "RefDate" : ISODate("2016-03-28T22:00:00.000Z"),
            "MarkedItems" : 72
        }, 
        {
            "idMark" : 20156,
            "idWarehouse" : 191,
            "idStock" : 31789,
            "ProgressivoDocumento" : 497,
            "Year" : 2016,
            "RefDate" : ISODate("2016-03-30T22:00:00.000Z"),
            "MarkedItems" : 144
        }, 
        {
            "idMark" : 23424,
            "idWarehouse" : 191,
            "idStock" : 31789,
            "ProgressivoDocumento" : 840,
            "Year" : 2016,
            "RefDate" : ISODate("2016-06-12T22:00:00.000Z"),
            "MarkedItems" : 3
        }
    ],
    "Details" : [ 
        {
            "idLSDetail" : 42781,
            "idStock" : 31789,
            "idStockOrig" : 54502,
            "StockCode" : "71529902",
            "Items" : 4532
        }
    ],   
    "MovementsOut" : [ 
        {
            "idMovementDetail" : 633,
            "idMovement" : 511,
            "MovedItems" : 3528 ,
            "idStockOrig" : null,
            "idStock" : 31789
        }
    ],
    "MovementsIn" : [ 
        {
            "idMovementDetail" : 715,
            "idMovement" : 570,
            "MovedItems" : 3528,
            "idStockOrig" : null,
            "idStock" : 33678
        }
    ]
}


/* 2 */
{
    "TemplateName" : "SAALottoStagionatura",
    "idStock" : 33678,
    "idWarehouse" : 190,
    "StockCode" : "71529902",
    "Marks" : [],
    "Details" : [ 
        {
            "idLSDetail" : 45206,
            "idStock" : 33678,
            "idStockOrig" : 56684,
            "StockCode" : "71529902",
            "Items" : 3528 

        }
    ],
   "MovementsOut" : [ 
        {
           "idMovementDetail" : 715,
            "idMovement" : 570,
            "MovedItems" : 3528,
            "idStockOrig" : null,
            "idStock" : 33678
        }
    ],
    "TrasferimentiInEntrata" : []
}
在我的提问中,我试图对这些动作进行分组

db.getCollection('Test')
.aggregate(
 [
      {$match: {"idWarehouse": 191, StockCode: "71529902" } }, 
      {$unwind: "$Details"}, 
      {$unwind: "$Marks"},       
      {$unwind: "$MovementsIn"},     
      {$unwind: "$MovementsOut"},     
       {
        $group : {
           _id : {  
               StockCode: "$idStock",
               StockCode: "$StockCode" 
               },

           tot: { $sum: "$Details.Items" },
           cer: { $sum: "$Marks.MarkedItems" },
           in: { $sum: "$MovementsIn.MovedItems" },
           out: { $sum: "$MovementsOut.MovedItems" }   
        }
      } 
   ]
)
我的期望应该是这样

{
    "_id" : {
        "StockCode" : "71529902"
    },
    "tot" : 13596,
    "cer" : 219,
    "in" : 3528,
    "out" : 7056
}

然而,我总是得到运动10584的全部总和。我错在哪里?

事实上,在3.2版之后的任何现代MongoDB版本中,您只需使用的是双裸调用,而不是:

这是因为从该版本开始,当您对数组(如$Details.Items)中的元素进行注释时,投影结果是在指定路径上找到的一个值数组。第二个附加功能是对数组求和,因此它在组中被调用到数组内容,然后作为文档之间的累加器

针对问题中的两个文档运行时返回结果:

/* 1 */
{
    "_id" : {
        "StockCode" : "71529902"
    },
    "tot" : 8060.0,
    "cer" : 219.0,
    "in" : 3528.0,
    "out" : 7056.0
}
在早期版本(如MongoDB 2.6)中,您可以通过将多个数组组合成一个数组来避免笛卡尔积,如果标识符和值实际上是唯一的,则可能使用:

db.getCollection('Test').aggregate([
  { "$project": {
    "StockCode": 1,
    "combined": { 
      "$setUnion": [
        { "$map": {
          "input": { "$ifNull": [ "$Details", [] ] },
          "as": "el",
          "in": { "id": "$idLSDetail", "k": "Details", "v": "$$el.Items" }
        }},
        { "$map": {
          "input": { "$ifNull": [ "$Marks", [] ] },
          "as": "el",
          "in": { "id": "$idMark", "k": "Marks", "v": "$$el.MarkedItems" }
        }},
        { "$map": {
          "input": { "$ifNull": [ "$MovementsIn", [] ] },
          "as": "el",
          "in": { "id": "$idMovementDetail", "k": "MoveIn", "v": "$$el.MovedItems" }
        }},  
        { "$map": {
          "input": { "$ifNull": [ "$MovementsOut", [] ] },
          "as": "el",
          "in": { "id": "$idMovementDetail", "k": "MoveOut", "v": "$$el.MovedItems" }
        }}
      ]
    }
  }},
  { "$unwind": "$combined" },
  { "$group": {
    "_id": {
      "StockCode": "$StockCode" 
    },
    "tot": {
      "$sum": {
        "$cond": {
          "if": { "$eq": [ "$combined.k", "Details" ] },
          "then": "$combined.v",
          "else": 0  
        }  
      }  
    },
    "cer": {
      "$sum": {
        "$cond": {
          "if": { "$eq": [ "$combined.k", "Marks" ] },
          "then": "$combined.v",
          "else": 0  
        }  
      }  
    },
    "in": {
      "$sum": {
        "$cond": {
          "if": { "$eq": [ "$combined.k", "MoveIn" ] },
          "then": "$combined.v",
          "else": 0  
        }  
      }  
    },
    "out": {
      "$sum": {
        "$cond": {
          "if": { "$eq": [ "$combined.k", "MoveOut" ] },
          "then": "$combined.v",
          "else": 0  
        }  
      }  
    }
  }}
])
在较旧的版本中,或者在不可能唯一性的情况下,可以分别替换每个数组,然后重复此过程,直到减少数组。然后,您可以将$group作为跨文档的最终值

但与上面一样,您需要小心,因为并非所有文档都有所有数组,这需要处理。在上面的示例中,我们可以只提供一个空数组,而不是初始$sum中的null。但是,一旦您单独使用,如果没有任何内容或内容为空,则会出现问题:

 db.getCollection('Test').aggregate([
  { "$project": {
     "StockCode": 1,
     "Details": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$Details", [] ] } }, 0] },
          [null],
          "$Details"
        ] 
     },
     "Marks": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$Marks", [] ] } }, 0] },
          [null],
          "$Marks"
        ] 
     },
     "MovementsIn": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$MovementsIn", [] ] } }, 0] },
          [null],
          "$MovementsIn"
        ] 
     },
     "MovementsOut": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$MovementsOut", [] ] } }, 0] },
          [null],
          "$MovementsOut"
        ] 
     }
  }},
  { "$unwind": "$Details" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$sum": "$Details.Items" },
    "Marks": { "$first": "$Marks" },
    "MovementsIn": { "$first": "$MovementsIn" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$Marks" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$sum": "$Marks.MarkedItems" },
    "MovementsIn": { "$first": "$MovementsIn" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$MovementsIn" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$first": "$cer" },
    "in": { "$sum": "$MovementsIn.MovedItems" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$MovementsOut" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$first": "$cer" },
    "in": { "$first": "$in" },
    "out": { "$sum": "$MovementsOut.MovedItems" }    
  }},
  { "$group": {
    "_id": {
      "StockCode": "$StockCode",
    },
    "tot": { "$sum": "$tot" },
    "cer": { "$sum": "$cer" },
    "in": { "$sum": "$in" },
    "out": { "$sum": "$out" }
  }}
])

因此,那里的测试需要确定阵列是否需要更换

非常清楚和完整的答案。非常感谢你!
 db.getCollection('Test').aggregate([
  { "$project": {
     "StockCode": 1,
     "Details": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$Details", [] ] } }, 0] },
          [null],
          "$Details"
        ] 
     },
     "Marks": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$Marks", [] ] } }, 0] },
          [null],
          "$Marks"
        ] 
     },
     "MovementsIn": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$MovementsIn", [] ] } }, 0] },
          [null],
          "$MovementsIn"
        ] 
     },
     "MovementsOut": { 
       "$cond": [
          { "$eq": [{ "$size": { "$ifNull": [ "$MovementsOut", [] ] } }, 0] },
          [null],
          "$MovementsOut"
        ] 
     }
  }},
  { "$unwind": "$Details" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$sum": "$Details.Items" },
    "Marks": { "$first": "$Marks" },
    "MovementsIn": { "$first": "$MovementsIn" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$Marks" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$sum": "$Marks.MarkedItems" },
    "MovementsIn": { "$first": "$MovementsIn" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$MovementsIn" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$first": "$cer" },
    "in": { "$sum": "$MovementsIn.MovedItems" },
    "MovementsOut": { "$first": "$MovementsOut" }    
  }},
  { "$unwind": "$MovementsOut" },
  { "$group": {
    "_id": "$_id",
    "StockCode": { "$first": "$StockCode" },
    "tot": { "$first": "$tot" },
    "cer": { "$first": "$cer" },
    "in": { "$first": "$in" },
    "out": { "$sum": "$MovementsOut.MovedItems" }    
  }},
  { "$group": {
    "_id": {
      "StockCode": "$StockCode",
    },
    "tot": { "$sum": "$tot" },
    "cer": { "$sum": "$cer" },
    "in": { "$sum": "$in" },
    "out": { "$sum": "$out" }
  }}
])