• mongodb入门(三)


    前言

    前面两节我们学习了 mongo 的一些基本操作以及多条件查询等,简单的业务拿前两节的内容组合基本已经可以实现了,但是 mongodb 的强大之处还没有体现出来,这节我们来学习 mongodb 强大的聚合查询功能。

    聚合查询
    1. 聚合操作的命令为“aggregate”,语法: collection.aggregate(“阶段1”,“阶段2”…“阶段N”)。
      看到这里,大家如果熟悉 java 的话,这个语法看着是不是有点java8 lambda 表达式的味道,或者是 CompletableFuture 的感觉,都是分阶段来处理数据。

      mongodb 的聚合操作可以有0个、1个或者多个阶段。 如果有0个阶段,则查询命令写为:db.user.aggregate(); 其作用与 db.user.find({}); 一样。

      实际工作中,一般情况下,并非所有的数据都需要被处理,因此大多数时候聚合的第一个阶段是数据筛选。然后针对筛选出来的数据做进一步处理。

      数据筛选的关键字为“$match”,语法:collection.aggregate([“$match”:{find的查询表达式}])。
      看下面的例子:

    // 查询年龄大于 18 并且姓名是 张三丰的用户信息
    // 使用 find 实现
    db.user.find({"age":{"$gt":18},"name":"张三丰"});
    // 使用 aggregate 实现
    db.user.aggregate([{"$match":{"age":{"$gt":18},"name":"张三丰"}}]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 数据转换

      我们前面学习了使用{“字段名”:0或者1} 的方式来实现我们返回指定的字段信息,那么在聚合查询中怎么实现这个功能呢?这里就要用到 KaTeX parse error: Expected '}', got 'EOF' at end of input: …集合.aggregate({"project":{“字段信息过滤语句”}})
      其中 字段信息过滤语句与 find 的第二个参数的用法一致。

    // 只输出 age 和 name
    db.user.aggregate(
        [
            {"$match":{"age":{"$gt":18}}},
            {"$project":{"_id":0,"age":1,"name":1}}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    // 修改现有字段 例如
    db.user.aggregate(
        [
            {"$match":{"age":{"$gt":18}}},
            {"$project":{"_id":0,"age":1,"name":1,"sex":"女"}}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    我们看到 sex 字段的结果已经被我们修改了,当然这里的修改只是对数据的一种处理,不会影响到集合中的原始数据。

    // 抽取嵌套字段
    db.user.aggregate(
        [
            {"$project":{"name":"$friend.name","age":"$friend.age"}}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    3. 特殊字段处理

    如果字段值是以 $ 开始的,并且后面的名字不存在与现有字段,则该字段无效(不会被添加到处理的数据中),如果后面的名字存在与现有字段,那么就会把该字段的值复制到这个新的字段:

    // hello 字段的值会被复制为 age 字段的值
    db.user.aggregate(
        [
            {"$match":{"age":{"$gt":18}}},
            {"$project":{"_id":0,"age":1,"name":1,"hello":"$age"}}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    但是有一种情况,新加这个字段的值本生就是$现有字段名 这个样子,而不是要复制现有字段的值,这时就需要使用到另一个关键字“$literal”,其用法也很简单:{字段名:{“$literal”:“字段值”}},如:

    db.user.aggregate(
        [
            {"$match":{"age":{"$gt":18}}},
            {"$project":{"_id":0,"age":1,"name":1,"hello":{"$literal":"$age"}}}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    大家对比上下两个案例就明白他的作用了。

    这里补充一点,有的小伙伴反馈,使用主键更新数据不生效,例如,现在集合中的数据是这样的:
    在这里插入图片描述
    此时,我想把李四的名字更新 小四,我们说过 _id 是主键,利用主键更新记录,于是就有了如下的语句

    db.user.updateOne({"_id":"62e7759f6959971a547354d4"},{"$set":{"name":"小四"}});
    // 执行完成,接下来就是见证奇迹的时刻了!
    db.user.aggregate();
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    在这里插入图片描述
    不是说好了,李四 改为 小四 了么?为什么没变化?
    这是因为 _id是一个特殊的字段,我们必须要使用 ObjectId()把这个id包起来才可以,上面的更新语句改为如下就可以了:

    db.user.updateOne({"_id":ObjectId("62e7759f6959971a547354d4")},{"$set":{"name":"小四"}});
    // 包括查询语句也一样
    db.user.find({"_id":ObjectId("62e7759f6959971a547354d4")});
    
    • 1
    • 2
    • 3

    这时我们发现,数据已经变成我们预期的了。
    在这里插入图片描述
    今天的内容就分享到这里了,下节我们继续学习聚合查询的其他用法,我们下节见。

    由于本人也是处于学习阶段,所有内容是看过资料以后自己实验得出,如有不妥之处还望各位批评指正,在下感激不尽。

  • 相关阅读:
    API接口采集商品评论数据,item_review-获得淘宝商品评论
    Pandas数据处理可视化
    Linux输入设备应用编程(触摸屏获取坐标信息)
    PyQt5应用开发-PyQt5对比其他python生态的界面开发工具
    Js逆向教程-11常见混淆AA和JJ
    matlab将十六进制转换为十进制(hex2dec函数)
    2024届通信工程保研经验分享(预推免入营即offer)
    C# 类型转换
    Go语言学习(三)-- 派生数据类型
    12030.LMK03000时钟合成器
  • 原文地址:https://blog.csdn.net/hxj413977035/article/details/126107587