MongoDB 聚合管道的字段投影($addFields,$set,$unset,$project)

news2024/11/19 5:36:46

上一篇我们介绍了MongoDB 聚合管道的文档筛选及分组统计:

        $match:文档过滤

        $group:文档分组,并介绍了分组中的常用操作:$addToSet,$avg,$sum,$min,$max等。

如果需要进一步了解可以参考:
MongoDB 聚合管道的文档筛选及分组统计https://blog.csdn.net/m1729339749/article/details/130034658这篇我们主要介绍使用聚合管道实现字段映射:

一、准备工作

初始化零食数据

db.goods.insertMany([
    { "_id": 1,  name: "薯片", size: "S", quantity: 10, price: 8, expirationTime: ISODate( "2023-08-08T00:00:00Z" ) },
    { "_id": 2,  name: "薯片", size: "L", quantity: 8, price: 12, expirationTime: ISODate( "2023-08-08T00:00:00Z" ) },
    { "_id": 3,  name: "牛肉干", size: "L", quantity: 5, price: 30, expirationTime: ISODate( "2023-10-10T00:00:00Z" ) },
    { "_id": 4,  name: "可口可乐", size: "S", quantity: 10, price: 3, expirationTime: ISODate( "2025-01-06T00:00:00Z" ) },
    { "_id": 5,  name: "可口可乐", size: "L", quantity: 6, price: 10, expirationTime: ISODate( "2025-01-06T00:00:00Z" ) },
    { "_id": 6,  name: "旺仔牛奶", size: "L", quantity: 10, price: 5, expirationTime: ISODate( "2023-08-10T00:00:00Z" )}
])

二、新增字段($addFields)

语法:{ $addFields: { <newField>: <expression>, ... } }

添加字段,从4.2开始后也可以使用$set增加字段

例子:在聚合数据中增加 comment 字段

db.goods.aggregate([
    {
        $addFields: { "comment": "我是新增加的" }
    }
])

此操作等效于:

db.goods.aggregate([
    {
        $set: { "comment": "我是新增加的" }
    }
])

聚合查询的结果如下:

{ "_id" : 1, "name" : "薯片", "size" : "S", "quantity" : 10, "price" : 8, "expirationTime" : ISODate("2023-08-08T00:00:00Z"), "comment" : "我是新增加的" }
{ "_id" : 2, "name" : "薯片", "size" : "L", "quantity" : 8, "price" : 12, "expirationTime" : ISODate("2023-08-08T00:00:00Z"), "comment" : "我是新增加的" }
{ "_id" : 3, "name" : "牛肉干", "size" : "L", "quantity" : 5, "price" : 30, "expirationTime" : ISODate("2023-10-10T00:00:00Z"), "comment" : "我是新增加的" }
{ "_id" : 4, "name" : "可口可乐", "size" : "S", "quantity" : 10, "price" : 3, "expirationTime" : ISODate("2025-01-06T00:00:00Z"), "comment" : "我是新增加的" }
{ "_id" : 5, "name" : "可口可乐", "size" : "L", "quantity" : 6, "price" : 10, "expirationTime" : ISODate("2025-01-06T00:00:00Z"), "comment" : "我是新增加的" }
{ "_id" : 6, "name" : "旺仔牛奶", "size" : "L", "quantity" : 10, "price" : 5, "expirationTime" : ISODate("2023-08-10T00:00:00Z"), "comment" : "我是新增加的" }

三、移除字段($unset)

语法:{ $unset: "<field>" }

        或 { $unset: [ "<field1>", "<field2>", ... ] }

移除字段,移除一个字段或者移除多个字段

例子:在聚合数据中移除  expirationTime字段

db.goods.aggregate([
    {    
        "$unset": "expirationTime"
    }
])

 聚合查询的结果如下:

{ "_id" : 1, "name" : "薯片", "size" : "S", "quantity" : 10, "price" : 8 }
{ "_id" : 2, "name" : "薯片", "size" : "L", "quantity" : 8, "price" : 12 }
{ "_id" : 3, "name" : "牛肉干", "size" : "L", "quantity" : 5, "price" : 30 }
{ "_id" : 4, "name" : "可口可乐", "size" : "S", "quantity" : 10, "price" : 3 }
{ "_id" : 5, "name" : "可口可乐", "size" : "L", "quantity" : 6, "price" : 10 }
{ "_id" : 6, "name" : "旺仔牛奶", "size" : "L", "quantity" : 10, "price" : 5 }

四、字段投影($project)

语法:{ $project: { <specification(s)> } }

对文档中的字段进行投影操作,例如:保留哪些字段、移除哪些字段、添加新的字段、重置字段的值等。

specifications的定义如下:

<field>: 1 or true:代表的是保留某个字段

<field>: 0 or false:代表的是移除某个字段

<field>: <expression>:代表的是添加新的字段或者重置字段的值

例子:移除商品的生产日期、编号,添加商品的总价值,并把size的值替换成小包装、大包装

db.goods.aggregate([
    {
        $project: {
            "name": 1,
            "price": 1,
            "quantity": 1,
            "size": {
                $cond: {
                    if: { $eq: [ "S", "$size"] },
                    then: "小包装",
                    else: "大包装"
                }
            },
            "totalWorth": { $multiply: [ "$quantity", "$price" ] }
        }
    }
])

解释一下给出的聚合查询语句:

(1) 保留name、price、quantity三个字段;

(2) 重置size的值,如果字段size的值与"S"相等,返回“小包装”作为值,否则返回“大包装”作为值;里面的表达式运算符我们先做简单的介绍,后面会出一篇文章单独介绍;

(3) 新增总价值字段totalWorth,将数量与价格相乘的结果作为新增字段的值;里面的表达式运算符我们先做简单的介绍,后面会出一篇文章单独介绍

下面我们看一下聚合查询的结果:

{ "_id" : 1, "name" : "薯片", "quantity" : 10, "price" : 8, "size" : "小包装", "totalWorth" : 80 }
{ "_id" : 2, "name" : "薯片", "quantity" : 8, "price" : 12, "size" : "大包装", "totalWorth" : 96 }
{ "_id" : 3, "name" : "牛肉干", "quantity" : 5, "price" : 30, "size" : "大包装", "totalWorth" : 150 }
{ "_id" : 4, "name" : "可口可乐", "quantity" : 10, "price" : 3, "size" : "小包装", "totalWorth" : 30 }
{ "_id" : 5, "name" : "可口可乐", "quantity" : 6, "price" : 10, "size" : "大包装", "totalWorth" : 60 }
{ "_id" : 6, "name" : "旺仔牛奶", "quantity" : 10, "price" : 5, "size" : "大包装", "totalWorth" : 50 }

可以看到里面的编号没有去除掉,原因是_id作为主键会自动保留,需要我们使用_id: 0 给强制去除掉

db.goods.aggregate([
    {
        $project: {
            "_id": 0,
            "name": 1,
            "price": 1,
            "quantity": 1,
            "size": {
                $cond: {
                    if: { $eq: [ "S", "$size"] },
                    then: "小包装",
                    else: "大包装"
                }
            },
            "totalWorth": { $multiply: [ "$quantity", "$price" ] }
        }
    }
])

再次执行聚合查询的结果如下:

{ "name" : "薯片", "quantity" : 10, "price" : 8, "size" : "小包装", "totalWorth" : 80 }
{ "name" : "薯片", "quantity" : 8, "price" : 12, "size" : "大包装", "totalWorth" : 96 }
{ "name" : "牛肉干", "quantity" : 5, "price" : 30, "size" : "大包装", "totalWorth" : 150 }
{ "name" : "可口可乐", "quantity" : 10, "price" : 3, "size" : "小包装", "totalWorth" : 30 }
{ "name" : "可口可乐", "quantity" : 6, "price" : 10, "size" : "大包装", "totalWorth" : 60 }
{ "name" : "旺仔牛奶", "quantity" : 10, "price" : 5, "size" : "大包装", "totalWorth" : 50 }

扩展:如何区分inclusion projection、exclusion projection

默认情况下是inclusion projection映射;

如果定义中出现的第一个非_id字段定义的映射为<field>: 0,则是exclusion projection映射;

如果定义中出现的第一个非_id字段定义的映射为<field>: 1,则是inclusion projection映射;

例子1:

db.goods.aggregate([
    {
        $project: {
            "_id": 0,
            "name": 1
        }
    }
])

如上面的例子,第一个非_id的字段定义的映射是"name": 1,则判断其是inclusion projection映射

例子2:

db.goods.aggregate([
    {
        $project: {
            "name": 0
        }
    }
])

如上面的例子,第一个非_id的字段定义的映射是"name": 0,则判断其是exclusion projection映射

扩展:inclusion projection中除_id:0外只能包含<field>: 1

           exclusion projection中除_id:1外只能包含<field>:0

 例子1:

db.goods.aggregate([
    {
        $project: { 
            "name": 1, 
            "size": 0 
        }
    }
])

执行上面的聚合查询会报错:

{
	"ok" : 0,
	"errmsg" : "Invalid $project :: caused by :: Cannot do exclusion on field size in inclusion projection",
	"code" : 31254,
	"codeName" : "Location31254"
}

分析原因:

第一个非_id的字段定义的映射是"name": 1,则判断其是inclusion projection映射,inclusion projection映射中除_id:0外只能包含<field>: 1,现在包含了"size": 0,则报了异常。

例子2:

db.goods.aggregate([
    {
        $project: { 
            "size": 0, 
            "name": 1
        }
    }
])

执行上面的聚合查询会报错:

{
	"ok" : 0,
	"errmsg" : "Invalid $project :: caused by :: Cannot do inclusion on field name in exclusion projection",
	"code" : 31253,
	"codeName" : "Location31253"
}

分析原因:

第一个非_id的字段定义的映射是"size": 0,则判断其是exclusion projection映射,exclusion projection映射中除_id:1外只能包含<field>: 0,现在包含了"name": 1,则报了异常。

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

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

相关文章

Ceph集群修复 osd 为 down 的问题

问题描述 由于突然断电了&#xff0c;导致 ceph 服务出现了问题&#xff0c;osd.1 无法起来 ceph osd tree解决方案 尝试重启 systemctl list-units |grep ceph systemctl restart ceph-f0e59898-71d4-11ec-924c-000c290a1a98osd.1.service发现重启无望&#xff0c;可采用…

国内企业使用敏捷开发的多吗?《2022中国企业敏捷实践白皮书》发布(附完整版下载)

通过2021-2022调研数据对比发现&#xff0c;受访者所在企业的敏捷团队占比从2021年的55%提升至2022年的63%&#xff0c;说明越来越多的中国企业正在从传统研发模式转变为敏捷研发模式&#xff0c;并不断扩大敏捷适用范围来促进企业整体敏捷转型&#xff1b; 与2021年的白皮书相…

android jetpack Navigation的使用(java)

简介 Navigation通过图形化的方式管理配置页面的切换。 基本使用 添加依赖 implementation androidx.navigation:navigation-fragment:2.5.3implementation androidx.navigation:navigation-ui:2.5.3创建xml文件&#xff08;添加导航图&#xff09;——nav_graph.xml nav_…

Java奠基】Java经典案例讲解

目录 卖飞机票 找质数 开发验证码 数组元素的复制 评委打分 数字加密 数字解密 抢红包 模拟双色球 二维数组 卖飞机票 需求&#xff1a;机票价格按照淡季旺季、头等舱和经济舱收费、输入机票原价、月份和头等舱或经济舱。按照如下规则计算机票价格&#xff1a; 旺季&…

ROS实践14 分布式通信

文章目录运行环境&#xff1a;思路&#xff1a;1.1 设置固定IP2.1 修改hosts文件3.1 检查是否成功通信4.1 修改bashrc5.1 演示运行环境&#xff1a; ubuntu20.04 noetic 宏基暗影骑士笔记本 思路&#xff1a; 主机启动roscore和乌龟速度订阅节点&#xff0c;从机启动乌龟键盘…

大模型时代下做科研的思路

总结zhu老师观点 Efficient 1.这篇论文是真的好orz&#xff0c;总结了目前的视频类模型 修改周边的一些参数&#xff0c;来训练&#xff0c;不改基础的模型&#xff08;太大了。。。没资源没卡&#xff09; 引申&#xff1a; prompt 是你想模型干什么你就给提示&#xff08…

python win环境 pip setuptools wheel安装

2023年。 今年的测试小学弟问我python这个安装怎么这么啥b。没有安装pip时 python setup.py install时需要setuptools&#xff0c;安装setuptools需要安装pip。 我看了看他的python是官网下的压缩包解压来的&#xff0c;内部非常干净。python-3.10.11 1. 安装pip 遇到这种情况…

“智慧赟”平台型经济引领行业新标杆

​  2021年&#xff0c;国家高度重视区块链行业发展&#xff0c;各部委发布的区块链相关政策已超60项&#xff0c;区块链不仅被写入“十四五”规划纲要中&#xff0c;各部门更是积极探索区块链发展方向&#xff0c;全方位推动区块链技术赋能各领域发展。在区块链产业具体内容…

【JavaEE】Spring中存储和获取Bean(使用注解)

目录 存储Bean 配置文件中设置扫描路径 使用注解存储Bean 五大类注解存储Bean 五大类注解之间的关系 为什么要有五大类注解 Bean方法注解存储方法返回值 注入Bean 属性注入 Setter方法注入 构造方法注入 Resource注解 存储Bean 上篇文章的存储Bean是在Spring的配置…

16.网络爬虫—字体反爬(实战演示)

网络爬虫—字体反爬一字体反爬原理二字体反爬模块FonttoolsTTF文件三FontCreator 14.0.0.2790FontCreatorPortable下载与安装四实战演示五后记前言&#xff1a; &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&#x1f396;️:Python领域新星…

一天吃透MySQL面试八股文

什么是MySQL MySQL是一个关系型数据库&#xff0c;它采用表的形式来存储数据。你可以理解成是Excel表格&#xff0c;既然是表的形式存储数据&#xff0c;就有表结构&#xff08;行和列&#xff09;。行代表每一行数据&#xff0c;列代表该行中的每个值。列上的值是有数据类型的…

python调用matlab源码函数

Background 关于在python中调用matlab函数&#xff0c;我之前已经写过两篇文章了&#xff0c;非常详细&#xff0c;且之前的方法可以不用安装matlab程序&#xff0c;只需要按照mcr运行环境就行了。具体可以参考&#xff1a;【java和python调用matlab程序详细记录】【Python 高效…

一文解析为什么进程地址空间中包括操作系统?

今天聊聊进程地址空间这点小事。说到进程的地址空间&#xff0c;大家可能都知道这样一张图&#xff1a; 这张图就是Linux程序运行起来后所谓的进程地址空间&#xff0c;这里包括我们熟悉的代码区、数据区、以及堆区和栈区&#xff0c;今天我们不讲解这些区域&#xff0c;而是重…

elementui的el-message重复点击,提示会一直叠加

1.问题&#xff1a; elementui的el-message连续点击按钮会出现一排提示&#xff0c;注意体验很不友好&#xff0c;而且也不好看 如下&#xff1a; 这种问题如何解决呢 ? 2.参考api elementui的官网有这个api&#xff0c;也就是说通过close这个方法可以解决 3.附上代码&a…

设计模式之美-结构型模式-装饰器模式

装饰器模式主要解决继承关系过于复杂的问题&#xff0c;通过组合来替代继承。指在不改变现有对象结构的情况下&#xff0c;动态地给该对象增加一些职责&#xff08;即增加其额外功能&#xff09;的模式&#xff0c;装饰器模式提供了比继承更有弹性的替代方案将功能附加到对象上…

4月20日专家谈:内网突遭攻击,安全人员一招有效处理

随着网络威胁的愈加频繁&#xff0c;企业面临的安全问题也越来越多&#xff0c;传统的安全能力在面对日益增长的安全问题时显得捉襟见肘。 SOAR借助安全编排和自动化技术&#xff0c;将人工操作和技术集成在一起&#xff0c;自动化完成安全处置&#xff0c;帮助企业更快地响应…

JavaScript【九】JavaScript BOM(浏览器对象模型)

文章目录&#x1f31f;前言&#x1f31f; Bom&#xff08;浏览器对象模型&#xff09;&#x1f31f;window对象&#xff1a;&#x1f31f;属性&#xff1a;&#x1f31f; 方法&#xff1a;&#x1f31f; 获取元素:&#x1f31f; 添加点击事件&#xff1a;&#x1f31f; 获取表单…

大数据Flink进阶(二十):Flink细粒度资源管理

文章目录 Flink细粒度资源管理 一、细粒度资源管理介绍 二、细粒度资源适用场景

关于合金电阻

合金电阻是一种具有高精度、高稳定性和高温度特性的电阻器件&#xff0c;广泛应用于各种电子设备中。选型合适的合金电阻并进行合理的设计&#xff0c;可以有效地提高电路的性能和可靠性。本文将从合金电阻的基本原理、选型方法及设计要点等方面进行详细介绍。 一、合金电阻的基…

简单认识下with和上下文管理器

with 对于系统资源如文件、数据库连接、socket&#xff0c;应用程序打开这些资源并执行完业务逻辑之后&#xff0c;必须关闭&#xff08;断开&#xff09;该资源。系统允许打开的最大文件数量是有限的&#xff0c;如果我们打开文件后没有及时关闭&#xff0c;极端情况下会出现…