MongoDB聚合:$unwind

使用$unwind可以对输入文档数组字段进行结构,为每个数组元素输出一个文档,并且每个输出文档都是输入文档数组字段的值。相当于将内嵌的数组文档提升到了顶层。

语法

可以通过字段路径或文档操作符来展开数组字段。

通过字段操作符展开

可以将数组字段路径传递给$unwind,如果字段值为null、不存在或者是个空数组,则$unwind不会输出文档。

指定的字段路径时,字段名前面必须使用$前缀,并用引号引起来。

{ $unwind: <field path> }

使用文档操作符选项

可以通过给$unwind传递一个文档来指定展开时的行为:

{$unwind:{path: <field path>,includeArrayIndex: <string>,preserveNullAndEmptyArrays: <boolean>}
}

|字段|类型|说明|
|path|string|数组字段的路径,字段名前面必须使用$前缀,并用引号引起来|
|includeArrayIndex|string|可选,给数组元素位置字段指定字段名,不能以$开始|
|preserveNullAndEmptyArrays|boolean|可选,缺省值为false。如果为true,当path为空、不存在或数组元素为空,$unwind输出文档,否则如果为false则不输出文档|

使用

非数组字段路径

  • 当操作符没有解析为数组,但不是缺失、空或空数组时,$unwind会将操作符视为单元素数组。

  • 当操作符为空、缺失或空数组时,$unwind会按照preserveNullAndEmptyArrays选项执行。

字段缺失

如果输入文档中不存在指定字段的路径或字段是个空数组,默认情况下$unwind会忽略输入文档且不输出文档。可以使用preserveNullAndEmptyArrays选项来强制输出文档。

举例

展开数组

inventory文档添加一个文档:

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

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

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

操作返回:

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

每个文档都与输入文档完全相同,只是sizes字段的值不同,该字段的值来自原始sizes数组。

缺失或数组为空

准备clothing集合数据:

db.clothing.insertMany([{ "_id" : 1, "item" : "Shirt", "sizes": [ "S", "M", "L"] },{ "_id" : 2, "item" : "Shorts", "sizes" : [ ] },{ "_id" : 3, "item" : "Hat", "sizes": "M" },{ "_id" : 4, "item" : "Gloves" },{ "_id" : 5, "item" : "Scarf", "sizes" : null }
])

下列情况下,$unwindsizes字段看做一个文档:

  • 字段存在
  • 字段的值不为空
  • 字段的值不是空数组

使用$unwind展开sizes数组:

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

操作返回:

{ _id: 1, item: 'Shirt', sizes: 'S' },
{ _id: 1, item: 'Shirt', sizes: 'M' },
{ _id: 1, item: 'Shirt', sizes: 'L' },
{ _id: 3, item: 'Hat', sizes: 'M' }
  • _id: 1的文档中,sizes是一个有元素的数组,$unwindsizes字段的每个元素生成了一个文档
  • _id: 3的文档中,sizes被解析为只有一个元素的数组
  • _id: 2_id: 4_id: 5文档则没有返回,因为sizes字段不能被解析为单元素数组。

注意:{path: <FIELD>}是可选的,下面的两个$unwind操作是等价的:

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

preserveNullAndEmptyArrays 和 includeArrayIndex

创建inventory2并插入下面数据:

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 }
])
preserveNullAndEmptyArrays

下面的$unwind操作使用preserveNullAndEmptyArrays选项,当sizes字段为null、缺失或空数组时,仍然输出文档。

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

输出包含了sizesnull、缺失或为空数组时的文档:

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

下面的$unwind操作使用includeArrayIndex选项,在输出文档中添加了数组元素索引字段。

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

操作展开了sizes数组,并为输出文档增加了一个数组元素索引字段arrayIndex,如果sizes字段不能被解析为一个有元素的数组,但又不是缺失、为空或空数组,则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 }

对展开的数组做分组汇总

创建并填充inventory2集合:

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

下面的操作展开sizes数组,并对展开文档的size字段进行分组:

db.inventory2.aggregate( [//阶段1{$unwind: { path: "$sizes", preserveNullAndEmptyArrays: true }},//阶段2{$group:{_id: "$sizes",averagePrice: { $avg: "$price" }}},//阶段3{$sort: { "averagePrice": -1 }}
] )
阶段1

$unwind阶段为sizes数组的每个元素输出一个文档,该阶段使用preserveNullAndEmptyArrays选项为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" : 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 }
阶段2

$group阶段根据sizes进行分组,并计算所有尺寸价格的平均值。该阶段完成后,生成下面的文档进入下一阶段:

{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }
阶段3

$sort阶段根据averagePrice字段值从大到小对文档进行排序,该阶段完成后返回下面的文档:

{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用 docker 部署程序?

如何用 docker 部署程序&#xff1f;这个问题有点笼统。 如果是MySQL、Redis这些&#xff0c;只需要拉取镜像&#xff0c;然后设置必要的配置&#xff0c;最终创建并运行实例即可。 如果你的应用是一个Java应用程序&#xff0c;使用Docker来部署它会涉及到Java特有的一些考虑…

c# Config 配置文件帮助类

public class ConfigHelper { #region 获取指定目录 AppSettings 配置文件值 /// <summary> /// 获取指定目录 AppSettings 配置文件值 /// </summary> /// <param name"key"></param> /// <…

LeetCode.144. 二叉树的前序遍历

题目 144. 二叉树的前序遍历 分析 这道题目是比较基础的题目&#xff0c;我们首先要知道二叉树的前序遍历是什么&#xff1f; 就是【根 左 右】 的顺序&#xff0c;然后利用递归的思想&#xff0c;就可以得到这道题的答案&#xff0c;任何的递归都可以采用 栈 的结构来实现…

片上网络NoC(1)——导论

一、多核时代的出现 自从20世纪90年代末引入多核芯片研究以来&#xff0c;片上网络已经成为一个重要且不断发展的研究领域。随着计算核心数量的不断增加&#xff0c;多核处理器被广泛应用在高端服务器、智能手机&#xff0c;甚至物联网&#xff08;Internet of Things,IoT)网关…

Microsoft Word 清除格式

Microsoft Word 清除格式 References 选择文本&#xff0c;用快捷键 Ctrl Shift N&#xff0c;可以快速清除格式。 选择文本&#xff0c;清除格式。 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

System V信号量

1.信号量 信号量本质上就是一把计数器(资源计数器) 表示资源数目的计数器,每一个执行流想访问公共资源内部的某一份资源&#xff0c;不应该让执行流先访问,而是先申请信号量资源,其实就是先对信号量计数器进行–操作,本质上,只要–成功&#xff0c;就完成了对资源的预订机制 如…

leetcode(矩阵)74. 搜索二维矩阵(C++详细解释)DAY7

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中…

Ubuntu编译和测试ITK4.13.1

安装不麻烦&#xff0c;环境配置挺麻烦&#xff0c;主要是gcc、cmake和ccmake的版本不匹配问题。 环境&#xff1a; gcc -- 7.5.0 cmake -- 3.15.2 ccmake -- 3.15.2 参考以下两篇博客安装&#xff1a; 1、 ITK的安装与测试&#xff08;Ubuntu系统&#xff09;_ubuntu20…

Confluence CVE-2023-22527利用工具

介绍 Confluence CVE 2021&#xff0c;2022&#xff0c;2023 利用工具&#xff0c;支持命令执行&#xff0c;哥斯拉&#xff0c;冰蝎 内存马注入 支持 Confluence 版本&#xff1a;CVE-2021-26084&#xff0c;CVE-2022-26134&#xff0c;CVE_2023_22515&#xff0c;CVE-2023-2…

计算机网络——06分组延时、丢失和吞吐量

分组延时、丢失和吞吐量 分组丢失和延时是怎样发生的 在路由器缓冲区的分组队列 分组到达链路的速率超过了链路输出的能力分组等待排到队头、被传输 延时原因&#xff1a; 当当前链路有别的分组进行传输&#xff0c;分组没有到达队首&#xff0c;就会进行排队&#xff0c;从…

【MySQL进阶之路】生产案例:大量数据刷盘导致的数据库性能抖动问题优化

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

【Docker】Docker Container(容器)

文章目录 一、什么是容器&#xff1f;二、为什么需要容器&#xff1f;三、容器的生命周期容器OOM容器异常退出容器暂停 四、容器命令详解docker createdocker logsdocker attachdocker execdocker startdocker stopdocker restartdocker killdocker topdocker statsdocker cont…

Apache 神禹(shenyu)源码阅读(一)——Admin向Gateway的数据同步(Admin端)

源码版本&#xff1a;2.6.1 单机源码启动项目 启动教程&#xff1a;社区新人开发者启动及开发防踩坑指南 源码阅读 前言 开了个新坑&#xff0c;也是第一次阅读大型项目源码&#xff0c;写文章记录。 在写文章前&#xff0c;已经跑了 Divide 插件体验了一下&#xff08;体…

Mac OS 取消隔离扩展属性

sudo xattr -rd com.apple.quarantine ${file} 扩展属性的大小通常被限制为明显小于最大文件大小的值。典型用途包括存储文档的作者、纯文本文档的字符编码或校验和、加密哈希或数字证书和自主访问控制信息。 在类 Unix系统中&#xff0c;扩展属性通常缩写为xattr。 从 macO…

elasticsearch 索引的监控

** 1. 监控索引的健康状态信息 ** 如果创建了一个索引test-3-2-1并且你想知道索引test-3-2-1的健康状态可以使用索引的cat端点&#xff0c;代码如下。 GET /_cat/indices/test-3-2-1?v&formatjson会得到类似于以下的健康状态监控信息 [{"health" : "ye…

DataEase

一. DataEase (一). 说明 安装文档 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务的改进与优化。DataEase 支持丰富的数据源连接&#xff0c;能够通过拖拉拽方式快速制作图表&#xff0c;并可以方便的与他人分…

比特币突然大涨

作者&#xff1a;秦晋 2月9日&#xff0c;除夕夜&#xff0c;比特币突然大涨&#xff0c;最高涨至48219美元&#xff0c;涨幅超6%。据CNBC报道&#xff0c;本周比特币已经上涨10.76%&#xff0c;创下自12月8日以来的最佳的一周。本周ETH上涨8.46%&#xff0c;成为自1月12日以来…

mac无法往硬盘里存东西 Mac硬盘读不出来怎么办 Mac硬盘格式 硬盘检测工具

mac有时候会出现一些问题&#xff0c;比如无法往硬盘里存东西&#xff0c;或者无法往硬盘上拷贝文件。这些问题会给用户带来很大的困扰&#xff0c;影响正常的工作和学习。那么&#xff0c;mac无法往硬盘里存东西&#xff0c;mac无法往硬盘上拷贝怎么办呢&#xff1f;软妹子将为…

DAY9.

1.选择芯片型号 2. 3. 4. 5. 6. 7.

相机图像质量研究(12)常见问题总结:光学结构对成像的影响--炫光

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…