当前位置: 首页 > article >正文

MongoDB聚合管道数组操作

数组表达式运算符判断数组中是否包含元素( i n ) 并获取元素索引 ( in)并获取元素索引( in)并获取元素索引(indexOfArray)

一、初始化成员数据

db.persons.insertMany([
    { "_id" : "1001", "name" : "张三", "fruits" : [ "apple", "orange" ] },
    { "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] },
    { "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] },
    { "_id" : "1004", "name" : "赵六", "fruits" : [ ] },
    { "_id" : "1005", "name" : "田七" },
])

二、包含元素($in)

语法:{ $in: [ , ] }

判断数组中是否包含某个元素

expression:代表的是元素

array expression:代表的是数组

例子:判断成员是否喜欢苹果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteApple": {
                $in: [ "apple", "$fruits" ]
            }
        }
    }
])

聚合查询的结果如下:

{
	"ok" : 0,
	"errmsg" : "$in requires an array as a second argument, found: missing",
	"code" : 40081,
	"codeName" : "Location40081"
}

发现报错了,原因是在编号为1005的成员中不存在fruits字段导致的。

这里我们需要**使用 i s A r r a y 断言数组操作进行聚合查询 < / f o n t > ∗ ∗ < f o n t s t y l e = " c o l o r : r g b ( 77 , 77 , 77 ) ; " > ,如果您对 isArray断言数组操作进行聚合查询</font>**<font style="color:rgb(77, 77, 77);">,如果您对 isArray断言数组操作进行聚合查询</font><fontstyle="color:rgb(77,77,77);">,如果您对isArray断言数组操作不太了解,可以参考:https://blog.csdn.net/m1729339749/article/details/130162535

下面我们使用$isArray断言数组操作改进聚合查询:

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteApple": {
                $cond: {
                    if: { $isArray: "$fruits" }, 
                    then: { $in: [ "apple", "$fruits" ] }, 
                    else: false
                }
            }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteApple" : true }
{ "_id" : "1002", "name" : "李四", "favoriteApple" : true }
{ "_id" : "1003", "name" : "王五", "favoriteApple" : true }
{ "_id" : "1004", "name" : "赵六", "favoriteApple" : false }
{ "_id" : "1005", "name" : "田七", "favoriteApple" : false }

三、获取元素索引($indexOfArray)

语法:{ $indexOfArray: [ , , , ] }

查询元素在数组中的索引位置

array expression:代表的是数组

search expression:代表的是待搜索的元素

start:可选,搜索的起始位置

end:可选,搜索的结束位置

搜索的范围是 [start, end) 即前开后闭

例子1:搜索水果apple的索引

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "indexApple": {
                $indexOfArray: [ "$fruits", "apple" ]
            }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "indexApple" : 0 }
{ "_id" : "1002", "name" : "李四", "indexApple" : 1 }
{ "_id" : "1003", "name" : "王五", "indexApple" : 1 }
{ "_id" : "1004", "name" : "赵六", "indexApple" : -1 }
{ "_id" : "1005", "name" : "田七", "indexApple" : null }

未查找到元素,返回-1

数组字段不存在,返回null

例子2:搜索水果apple的索引,起始位置(0)结束位置(1)

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "indexApple": {
                $indexOfArray: [ "$fruits", "apple", 0 ,1 ]
            }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "indexApple" : 0 }
{ "_id" : "1002", "name" : "李四", "indexApple" : -1 }
{ "_id" : "1003", "name" : "王五", "indexApple" : -1 }
{ "_id" : "1004", "name" : "赵六", "indexApple" : -1 }
{ "_id" : "1005", "name" : "田七", "indexApple" : null }

与例子1中聚合查询的结果比较我们会发现:

编号为1002,1003的成员数据中没有检索到元素,说明检索的范围不包含结束位置对应的索引。

start,end检索的范围是[start, end),包含起始位置对应的索引,不包含结束位置对应的索引

数组表达式运算符截取数组($slice)

数组表达式运算符主要用于文档中数组的操作,本篇我们主要介绍数组表达式运算符中用于截取数组的操作,下面我们进行详细介绍:

一、语法

{ $slice: [ , ] }

或者 { $slice: [ , , ] }

获取数组中指定范围内的元素组成一个新的数组

:代表的是数组

:代表的是起始位置索引(包含此位置的元素)

:代表的是获取N个元素

二、准备工作

初始化成员数据

db.persons.insertMany([
    { "_id" : "1001", "name" : "张三", "fruits" : [ "apple", "pineapple", "orange" ] },
    { "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple", "pineapple" ] },
    { "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange", "watermelon" ] },
    { "_id" : "1004", "name" : "赵六", "fruits" : [ ] },
    { "_id" : "1005", "name" : "田七" },
])

三、示例

例子1:找到每个人最喜欢吃的前两个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteFruits": { $slice: [ "$fruits", 2 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteFruits" : [ "apple", "pineapple" ] }
{ "_id" : "1002", "name" : "李四", "favoriteFruits" : [ "banana", "apple" ] }
{ "_id" : "1003", "name" : "王五", "favoriteFruits" : [ "banana", "apple" ] }
{ "_id" : "1004", "name" : "赵六", "favoriteFruits" : [ ] }
{ "_id" : "1005", "name" : "田七", "favoriteFruits" : null }

例子2:找到每个人最喜欢吃的最后两个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteFruits": { $slice: [ "$fruits", -2 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteFruits" : [ "pineapple", "orange" ] }
{ "_id" : "1002", "name" : "李四", "favoriteFruits" : [ "apple", "pineapple" ] }
{ "_id" : "1003", "name" : "王五", "favoriteFruits" : [ "orange", "watermelon" ] }
{ "_id" : "1004", "name" : "赵六", "favoriteFruits" : [ ] }
{ "_id" : "1005", "name" : "田七", "favoriteFruits" : null }

(1)****字段未定义时,结果为null;

(2)未找到元素,结果为[ ]

(3){ $slice: [ , ] } 语法中 n为正数,代表的是从前往后取N个元素,n为负数,代表的是从后往前取N个元素

例子3:找到每个人最喜欢吃的第二个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteFruits": { $slice: [ "$fruits", 1, 1 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteFruits" : [ "pineapple" ] }
{ "_id" : "1002", "name" : "李四", "favoriteFruits" : [ "apple" ] }
{ "_id" : "1003", "name" : "王五", "favoriteFruits" : [ "apple" ] }
{ "_id" : "1004", "name" : "赵六", "favoriteFruits" : [ ] }
{ "_id" : "1005", "name" : "田七", "favoriteFruits" : null }

例子4:假如position为负数,会如何处理

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteFruits": { $slice: [ "$fruits", -2, 1 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteFruits" : [ "pineapple" ] }
{ "_id" : "1002", "name" : "李四", "favoriteFruits" : [ "apple" ] }
{ "_id" : "1003", "name" : "王五", "favoriteFruits" : [ "orange" ] }
{ "_id" : "1004", "name" : "赵六", "favoriteFruits" : [ ] }
{ "_id" : "1005", "name" : "田七", "favoriteFruits" : null }

例子5:假如position = -10,会如何处理

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "favoriteFruits": { $slice: [ "$fruits", -10, 1 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "favoriteFruits" : [ "apple" ] }
{ "_id" : "1002", "name" : "李四", "favoriteFruits" : [ "banana" ] }
{ "_id" : "1003", "name" : "王五", "favoriteFruits" : [ "banana" ] }
{ "_id" : "1004", "name" : "赵六", "favoriteFruits" : [ ] }
{ "_id" : "1005", "name" : "田七", "favoriteFruits" : null }

如果position为负数,则从后往前确定起始位置,当向前移动的位置超过了数组长度,则起始位置为0;然后再从前往后获取N个元素组成新的数组。

数组表达式运算符过滤数组($filter)

数组表达式运算符主要用于文档中数组的操作,本篇我们主要介绍数组表达式运算符中用于过滤数组的操作,下面我们进行详细介绍:

一、语法

{
   $filter:
      {
         input: <array>,
         cond: <expression>,
         as: <string>,
         limit: <number expression>
      }
}

其中,

input:代表的是数组

cond:代表的是条件

as:可选,定义的变量,用于接收数组中的当前元素,如果未定义在cond表达式中可以使用$$this获取数组中的当前元素

limit:可选,限制数组中元素的个数

二、准备工作

初始化零食数据

db.goods.insertMany([
    { "_id" : 1, "name" : "薯片", "types" : [ 
        { "size" : "S", "quantity" : 10, "price" : 8 },
        { "size" : "L", "quantity" : 8, "price" : 12 } 
    ]},
    { "_id" : 2, "name" : "牛肉干", "types" : [ 
        { "size" : "L", "quantity" : 5, "price" : 30} 
    ]},
    { "_id" : 3, "name" : "可口可乐", "types" : [ 
        { "size" : "S", "quantity" : 10, "price" : 3 }, 
        { "size" : "L", "quantity" : 6, "price" : 10 } 
    ]},
    { "_id" : 4, "name" : "旺仔牛奶", "types" : [ 
        { "size" : "L", "quantity" : 10, "price" : 5 } 
    ]}
])

三、示例

例子1:只查看型号为L的型号信息

db.goods.aggregate([
    {
        $project: {
            types: {
                $filter: {
                    input: "$types",
                    cond: { $eq: [ "$$this.size", "L" ] }
                }
            }
        }
    }
])

等效于:

db.goods.aggregate([
    {
        $project: {
            types: {
                $filter: {
                    input: "$types",
                    as: "type",
                    cond: { $eq: [ "$$type.size", "L" ] }
                }
            }
        }
    }
])

聚合查询的结果如下:

{ "_id" : 1, "types" : [ { "size" : "L", "quantity" : 8, "price" : 12 } ] }
{ "_id" : 2, "types" : [ { "size" : "L", "quantity" : 5, "price" : 30 } ] }
{ "_id" : 3, "types" : [ { "size" : "L", "quantity" : 6, "price" : 10 } ] }
{ "_id" : 4, "types" : [ { "size" : "L", "quantity" : 10, "price" : 5 } ] }

as用于定义一个存储数组中当前元素的变量,使用变量时前面需要加上 “$$”;

如果不使用as定义变量,也可以使用 $$this 访问数组中的当前元素

例子2:对超过5元的型号进行查询

db.goods.aggregate([
    {
        $project: {
            types: {
                $filter: {
                    input: "$types",
                    as: "type",
                    cond: { $gt: [ "$$type.price", 5 ] }
                }
            }
        }
    }
])

聚合查询的结果如下:

{ "_id" : 1, "types" : [ { "size" : "S", "quantity" : 10, "price" : 8 }, { "size" : "L", "quantity" : 8, "price" : 12 } ] }
{ "_id" : 2, "types" : [ { "size" : "L", "quantity" : 5, "price" : 30 } ] }
{ "_id" : 3, "types" : [ { "size" : "L", "quantity" : 6, "price" : 10 } ] }
{ "_id" : 4, "types" : [ ] }

多个查询条件

cond: {
  $and: [
    { $gte: ['$$item.timestamp_start', fromTimestamp] },
    { $lt: ['$$item.timestamp_start', toTimestamp] }
  ]
}

数组表达式运算符( a r r a y E l e m A t , arrayElemAt, arrayElemAtfirst,$last)

数组表达式运算符主要用于文档中数组的操作,本篇我们主要介绍数组表达式运算符中用于获取数组元素的操作,下面我们进行详细介绍:

一、准备工作

初始化成员数据

db.persons.insertMany([
    { "_id" : "1001", "name" : "张三", "fruits" : [ "apple", "orange" ] },
    { "_id" : "1002", "name" : "李四", "fruits" : [ "banana", "apple" ] },
    { "_id" : "1003", "name" : "王五", "fruits" : [ "banana", "apple", "orange" ] },
    { "_id" : "1004", "name" : "赵六", "fruits" : [ ] },
    { "_id" : "1005", "name" : "田七" },
])

二、获取数组中指定元素($arrayElemAt)

语法:{ $arrayElemAt: [ , ] }

获取数组中指定索引位置的元素

:代表的是数组

:代表的是索引,索引为正数代表的是从前往后查找元素、为负数代表的是从后往前查找元素

数组的索引从0开始,最大值为数组的长度-1

例子1:找到每个人最喜欢吃的第一个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "firstFruit": { $arrayElemAt: [ "$fruits", 0 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "firstFruit" : "apple" }
{ "_id" : "1002", "name" : "李四", "firstFruit" : "banana" }
{ "_id" : "1003", "name" : "王五", "firstFruit" : "banana" }
{ "_id" : "1004", "name" : "赵六" }
{ "_id" : "1005", "name" : "田七", "firstFruit" : null }

字段未定义时,结果为null,

索引超过数组边界则不返回结果。

例子2:找到每个人最喜欢吃的最后一个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "lastFruit": { $arrayElemAt: [ "$fruits", -1 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "lastFruit" : "orange" }
{ "_id" : "1002", "name" : "李四", "lastFruit" : "apple" }
{ "_id" : "1003", "name" : "王五", "lastFruit" : "orange" }
{ "_id" : "1004", "name" : "赵六" }
{ "_id" : "1005", "name" : "田七", "lastFruit" : null }

索引为负数代表的是从后往前查找元素

三、获取数组中第一个元素($first)

语法:{ $first: }

获取数组中第一个元素

例子:找到每个人最喜欢吃的第一个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "firstFruit": { $first: "$fruits" }
        }
    }
])

等效于:

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "firstFruit": { $arrayElemAt: [ "$fruits", 0 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "firstFruit" : "apple" }
{ "_id" : "1002", "name" : "李四", "firstFruit" : "banana" }
{ "_id" : "1003", "name" : "王五", "firstFruit" : "banana" }
{ "_id" : "1004", "name" : "赵六" }
{ "_id" : "1005", "name" : "田七", "firstFruit" : null }

四、获取数组中最后一个元素($last)

语法:{ $last: }

获取数组中最后一个元素

例子:找到每个人最喜欢吃的最后一个水果

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "lastFruit": { $last: "$fruits" }
        }
    }
])

等效于:

db.persons.aggregate([
    {
        $project: {
            "name": 1,
            "lastFruit": { $arrayElemAt: [ "$fruits", -1 ] }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "1001", "name" : "张三", "lastFruit" : "orange" }
{ "_id" : "1002", "name" : "李四", "lastFruit" : "apple" }
{ "_id" : "1003", "name" : "王五", "lastFruit" : "orange" }
{ "_id" : "1004", "name" : "赵六" }
{ "_id" : "1005", "name" : "田七", "lastFruit" : null }

http://www.kler.cn/a/397505.html

相关文章:

  • 微服务瞎写
  • PMP--一、二、三模、冲刺--分类--变更--技巧--特点
  • C++ | Leetcode C++题解之第560题和为K的子数组
  • 如何在uniapp中获取和修改Web项目的Cookie
  • MySQL【五】
  • reduce-scatter:适合分布式计算;Reduce、LayerNorm和Broadcast算子的执行顺序对计算结果的影响,以及它们对资源消耗的影响
  • 集群搭建高可用
  • IPv6路由基础
  • Ubuntu24.04挂载磁盘
  • Docker实践与应用举例:构建高效开发与部署环境
  • __VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined
  • Spring Boot 集成 Kettle
  • 计算机毕业设计Hadoop+大模型空气质量预测 空气质量可视化 空气质量分析 空气质量爬虫 Spark 机器学习 深度学习 Django 大模型
  • 【网页设计】HTML5 和 CSS3 提高
  • web——upload-labs——第二关
  • Linux应用层学习——Day2(文件IO)
  • 【青牛科技】D54123 漏电保护电路介绍及应用
  • 刘艳兵-DBA037-在ASM实例中,如下哪个参数是必须的?
  • git没有识别出大写字母改成小写重命名的文件目录
  • C++(Qt)软件调试---内存分析工具Heob(26)
  • 借助 Pause 容器调试 Pod
  • 【微软:多模态基础模型】(3)视觉生成
  • docker ce 阿里云Linux安装
  • 类与对象;
  • 赋予孩子光明未来:孤独症自闭症干预机构的专业治疗
  • [AI] 【提高认知】自动翻译技术的演变:从规则系统到深度学习的崛起