MongoDB 考虑文档排名获取组的平均值

MongoDB Get average of group considering rank of document

我整理的文件如下:

{ 
   "_id": "abcde1",
   "value" : 300
},
{ 
   "_id": "abcde2",
   "value" : 200
},
{ 
   "_id": "abcde3",
   "value" : 400
},
{ 
   "_id": "abcde4",
   "value" : 500
},
{ 
   "_id": "abcde5",
   "value" : 600
}

即 我想要像在单个查询中一样匹配的前 2 个、前 4 个和所有 5 个文档的“_id”的平均值:

{
    "value_2" : 250,   // Average of first 2 documents
    "value_4" : 350,    // Average of first four documents
    "value_5" : 400     // Average of all 5 documents
}

是否可以根据文档的等级对文档进行分组。

我可以在 3 个单独的查询中得到 3 个结果。是否可以在单个查询中?

您可以尝试运行以下管道:

db.collection.aggregate([
    // previous pipeline here
    {
        "$group": {
            "_id": null,
            "values": { "$push": "$value" }                
        }
    },
    { "$unwind": { "path": "$values", "includeArrayIndex": "rank"  } },
    {
        "$group": {
            "_id": null,
            "value_2_sum": {
                "$sum": { 
                    "$cond": [
                        { "$lt": ["$rank", 2] },
                        "$values",
                        0
                    ]
                }
            },
            "value_2_count": {
                "$sum": { 
                    "$cond": [
                        { "$lt": ["$rank", 2] },
                        1,
                        0
                    ]
                }
            },
            "value_4_sum": {
                "$sum": { 
                    "$cond": [
                        { "$lt": ["$rank", 4] },
                        "$values",
                        0
                    ]
                }
            },
            "value_4_count": {
                "$sum": { 
                    "$cond": [
                        { "$lt": ["$rank", 4] },
                        1,
                        0
                    ]
                }
            },
            "value_5": { "$avg": "$values" }
        }
    },
    {
        "$project": {
            "value_2" : { "$divide": ["$value_2_sum", "$value_2_count"] },   // Average of first 2 documents
            "value_4" : { "$divide": ["$value_4_sum", "$value_4_count"] },    // Average of first four documents
            "value_5" : 1
        }
    }
])

您可以使用 $facet 聚合阶段:

// { _id: "abcde1", value: 300 }
// { _id: "abcde2", value: 200 }
// { _id: "abcde3", value: 400 }
// { _id: "abcde4", value: 500 }
// { _id: "abcde5", value: 600 }
db.collection.aggregate([

  { $facet: {
    value_2: [ { $limit: 2 }, { $group: { _id: null, value_2: { $avg: "$value" } } } ],
    value_4: [ { $limit: 4 }, { $group: { _id: null, value_4: { $avg: "$value" } } } ],
    value_5: [ { $limit: 5 }, { $group: { _id: null, value_5: { $avg: "$value" } } } ]
  }},
  // {
  //   value_2: [ { _id: null, value_2: 250 } ],
  //   value_4: [ { _id: null, value_4: 350 } ],
  //   value_5: [ { _id: null, value_5: 400 } ]
  // }

  { $set: {
    value_2: { $first: "$value_2.value_2" },
    value_4: { $first: "$value_4.value_4" },
    value_5: { $first: "$value_5.value_5" }
  }}
])
// { "value_2" : 250, "value_4" : 350, "value_5" : 400 }

$facet 阶段允许我们在同一个输入文档集上的单个阶段中 运行 多个聚合管道。每个子管道在输出文档中都有自己的字段,其结果存储为文档数组。

因此,每个字段都由其自己的聚合管道生成,其第一阶段是简单的 $limit,然后是 $group 阶段,该阶段将生成 $avg(平均值)所有考虑的文件。

管道的第二部分($set 阶段)用于将 $facet 输出清理为您希望的格式。