mongodb Aggregation聚合操作之$unwind

在上一篇 mongodb Aggregation聚合操作之$project 中详细介绍了mongodb聚合操作中的$project使用以及参数细节。本篇将开始介绍Aggregation聚合操作中的unwind操作。

说明:

解析输入文档中的数组字段,为每个元素输出一个文档。每个输出文档都是输入文档,数组字段的值被元素替换。如果字段值为null、缺失或数组为空,则$unwind不会输出文档。


语法:

{ $unwind: }


可以将文档传递给$unwind以指定各种行为选项。

{

  $unwind:

    {

      path: ,

      includeArrayIndex: ,

      preserveNullAndEmptyArrays:

    }

}


参数解析:

path:string类型,数组字段的字段路径。若要指定字段路径,请在字段名称前加上美元符号$并将其括在引号中。

includeArrayIndex:string类型,可选的。用于保存元素的数组索引的新字段的名称。新字段名称不能以美元符号$开头。

preserveNullAndEmptyArrays:boolean类型,可选的。如果为真,如果路径为空、丢失或数组为空,则$unwind输出文档。如果为false,如果路径为空、丢失或数组为空,则$unwind不输出文档。默认值为false。

1. 示例

1.1. 简单示例


初始化数据:

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


示例:按照sizes字段拆分数据

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


结果:

{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }

{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }

{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }

1.2. 拆分数组字段是null或者[]数据


初始化数据:

db.inventory2.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字段中的每个元素返回一个文档。如果size字段没有解析为数组,但没有丢失、null或空数组,则$unwind将非数组操作数视为单个元素数组。

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

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


结果:

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }

{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }


示例:下面的$unwind操作使用includeArrayIndex选项在输出中包含数组索引。

db.inventory2.aggregate( [

  {

    $unwind:

      {

        path: "$sizes",

        includeArrayIndex: "arrayIndex"

      }

   }])


结果:

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S", "arrayIndex" : NumberLong(0) }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M", "arrayIndex" : NumberLong(1) }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L", "arrayIndex" : NumberLong(2) }

{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M", "arrayIndex" : null }


示例:下面的$unwind操作使用preserveNullAndEmptyArrays选项来包含size字段为null、缺失或空数组的文档。


db.inventory2.aggregate( [

   { $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }

] )


{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }

{ "_id" : 2, "item" : "EFG", "price" : NumberDecimal("120") }

{ "_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 }




1.3. 拆分数组字段并分组


初始化数据:

db.inventory2.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 }

])


示例:下面的管道将展开大小数组,并将产生的文档按展开后的大小值进行分组:

db.inventory2.aggregate( [

   // First Stage

   {

     $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true }

   },

   // Second Stage

   {

     $group:

       {

         _id: "$sizes",

         averagePrice: { $avg: "$price" }

       }

   },

   // Third Stage

   {

     $sort: { "averagePrice": -1 }

   }

] )


结果:

{ "_id" : "M", "averagePrice" : NumberDecimal("120") }

{ "_id" : "L", "averagePrice" : NumberDecimal("80") }

{ "_id" : "S", "averagePrice" : NumberDecimal("80") }

{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }

1.4. 拆分嵌入式数组文档


初始化数据:

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" ] }

          }

      }

  }

])


结果:

{ "_id" : "writing", "totalSalesAmount" : NumberDecimal("60.00") }

{ "_id" : "stationary", "totalSalesAmount" : NumberDecimal("264.45") }

{ "_id" : "electronics", "totalSalesAmount" : NumberDecimal("800.00") }

{ "_id" : "school", "totalSalesAmount" : NumberDecimal("104.85") }

    { "_id" : "office", "totalSalesAmount" : NumberDecimal("1019.60") }

你可能感兴趣的:(mongodb Aggregation聚合操作之$unwind)