1.$unwind

拆分($unwind) 可以将数组中的每一个值拆分为单独的文档,如下所示

mongodb4.4 Aggregation《二》_数据

语法:

{
  $unwind:
    {
      path: <field path>,
      includeArrayIndex: <string>,
      preserveNullAndEmptyArrays: <boolean>
    }
}
path                       数组字段的字段路径。要指定字段路径,请在字段名前面加上美元符号$,并用引号括起来。
includeArrayIndex          可选的。 一个新字段的名称,用于保存元素的数组索引。 名称不能以美元符号$开头。
preserveNullAndEmptyArrays 可选。如果为true,则如果路径为null、缺少或空数组,$undend将输出文档。如果为false,如果路径为null、缺少或空数组,$undend不输出文档。默认值为false。

缺少字段

如果为输入文档中不存在的字段指定路径,或者该字段是空数组,$undend默认情况下会忽略输入文档,并且不会输出该输入文档的文档。

版本3.2中的新功能:要输出缺少数组字段、null或空数组的文档,请使用preserveNullandEmptyArray选项。

(1).例子,Unwind Array(拆分数组)

插入基础数据

db.inventory_unwind.insertOne({ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })

以下聚合使用$ unwind阶段为sizes数组中的每个元素输出文档

wang> db.inventory_unwind.find()
{ "_id" : 1, "item" : "ABC1", "sizes" : [ "S", "M", "L" ] }
wang> 
wang> db.inventory_unwind.aggregate( [ { $unwind : "$sizes" } ] )
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }
wang> 
wang> 
(2).例子,includeArrayIndex和preserveNullAndEmptyArrays

插入基础数据

db.inventory_unwind2.insertMany([
  { "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
  { "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
  { "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
  { "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
  { "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75"), "sizes" : null }
])

以下unwind操作是等效的,并为size字段中的每个元素返回一个文档。如果sizes字段不能解析为数组,为null、缺少或空数组,undend不输出文档。

db.inventory_unwind2.aggregate( [ { $unwind: "$sizes" } ] )
db.inventory_unwind2.aggregate( [ { $unwind: { path: "$sizes" } } ] )

mongodb4.4 Aggregation《二》_字段_02

includeArrayIndex

以下$unwind操作使用includeArrayIndex选项将数组索引包括在输出中。

db.inventory_unwind2.aggregate( [
  {
    $unwind:
      {
        path: "$sizes",
        includeArrayIndex: "arrayIndex"
      }
   }])

mongodb4.4 Aggregation《二》_数组_03

preserveNullAndEmptyArrays

下面的$unwind操作使用prepareNullAndEmptyArrays选项来包含其size字段为null,缺少或为空数组的文档。

db.inventory_unwind2.aggregate( [
   { $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }
] )

mongodb4.4 Aggregation《二》_数据_04

(3).Group by Unwound Values

拆分后进行分组排序

db.inventory_unwind2.aggregate( [
   // First Stage
   {
     $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true }
   },
   // Second Stage
   {
     $group:
       {
         _id: "$sizes",
         averagePrice: { $avg: "$price" }
       }
   },
   // Third Stage
   {
     $sort: { "averagePrice": -1 }
   }
] )

mongodb4.4 Aggregation《二》_数组_05

(4).Unwind Embedded Arrays(拆分嵌套数组)

插入基础数据

db.sales.insertMany([
  {
    _id: "1",
    "items" : [
     {
      "name" : "pens",
      "tags" : [ "writing", "office", "school", "stationary" ],
      "price" : NumberDecimal("12.00"),
      "quantity" : NumberInt("5")
     },
     {
      "name" : "envelopes",
      "tags" : [ "stationary", "office" ],
      "price" : NumberDecimal("1.95"),
      "quantity" : NumberInt("8")
     }
    ]
  },
  {
    _id: "2",
    "items" : [
     {
      "name" : "laptop",
      "tags" : [ "office", "electronics" ],
      "price" : NumberDecimal("800.00"),
      "quantity" : NumberInt("1")
     },
     {
      "name" : "notepad",
      "tags" : [ "stationary", "school" ],
      "price" : NumberDecimal("14.95"),
      "quantity" : NumberInt("3")
     }
    ]
  }
])

以下操作按其标签对出售的商品进行分组,并计算每个标签的总销售额。

db.sales.aggregate([
  // First Stage
  { $unwind: "$items" },

  // Second Stage
  { $unwind: "$items.tags" },

  // Third Stage
  {
    $group:
      {
        _id: "$items.tags",
        totalSalesAmount:
          {
            $sum: { $multiply: [ "$items.price", "$items.quantity" ] }
          }
      }
  }
])

mongodb4.4 Aggregation《二》_数组_06