• mongodb入门(四)


    前言

    经过前面的小节,我们已经了解了 mongodb 的大部分功能,今天这节我们来进一步挖掘 mongodb 聚合查询的功能。

    分组操作

    分组操作对应的关键字为“$group”,它的作用是根据给出的字段 key,把所有key的值相同的记录放在一起进行运算。这些运行包括常见的“求和($sum)”“计算平均数($avg)”“最大值($max)”“最小值 ($min)”等。

    为了便于演示,我们新建一个集合并插入一些数据:

    // 创建集合 info
    db.createCollection("info");
    // 向 info 集合中插入数据
    db.info.insertMany(
        [
            {"name":"Lucy","hire_date":"2022/7/1","score":50},
            {"name":"Lili","hire_date":"2022/7/1","score":57},
            {"name":"Hanmeimei","hire_date":"2022/7/2","score":64},
            {"name":"Lucy","hire_date":"2022/7/3","score":78},
            {"name":"Hanmeimei","hire_date":"2022/7/4","score":77},
            {"name":"Lili","hire_date":"2022/7/8","score":82},
            {"name":"Lucy","hire_date":"2022/7/8","score":88},
            {"name":"Hanmeimei","hire_date":"2022/8/8","score":95}
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 现在使用分组操作来去重。分组去重的语法为:db.集合.aggregate([{“KaTeX parse error: Expected '}', got 'EOF' at end of input: group":{"_id":"去重的字段”}}])
      例如,我们对 name 字段去重,则有:
    db.info.aggregate([{"$group":{"_id":"$name"}}]);
    
    • 1

    在这里插入图片描述
    2. 去重并选择最新或最老的数据

    // 以name为基准去重,然后取各个字段的最新数据
    db.info.aggregate(
        [
            {"$group": {
                    "_id":"$name",
                    "date": {
                        "$last":"$hire_date"
                    },
                    "score": {
                        "$last":"$score"
                    }
                }
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    这里的关键字“$last”表示取最后一条记录。在 mongodb 中,老数据先插入,新数据后插入,所以每一组的最后一条就是最新插入的数据。

    “last”的反义词是“first”,所以关键字“$first”的意思是取 第一条,即是最早插入的数据。

    db.info.aggregate(
        [
            {"$group": {
                    "_id":"$name",
                    "date": {
                        "$first":"$hire_date"
                    },
                    "score": {
                        "$first":"$score"
                    }
                }
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    3. 分组并计算统计值

    db.getCollection("info").aggregate(
        [
            {
                "$group": {
                    "_id": "$name",
                    "max_score": {"$max":"$socre"},
                    "min_score": {"$min":"$score"},
                    "sum_score": {"$sum":"$score"},
                    "savg_score": {"$avg":"$score"}
                }
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    “$sum”的值还可以使用数字“1”,这样查询语句就变成了统 计每一个分组内有多少条记录。
    4. 拆分数组
    之前我们看到了 user 集合中的 price 和 intersts 值的类型是数组,其实我们可以把这个数据中的每个元素拆分为一条记录,这里就需要用到 KaTeX parse error: Expected '}', got 'EOF' at end of input: …o.aggregate([{"unwind":“$字段名”}])

    db.user.aggregate([{"$unwind":"$price"}]);
    
    • 1

    在这里插入图片描述
    “$unwind”一次只能拆开一个数组,如果还要把“price”字段拆开, 则可以让第一次运行的结果再走一次“$unwind”阶段。

    db.user.aggregate([{"$unwind":"$price"},{"$unwind":"$intersts"}]);
    
    • 1

    在这里插入图片描述

    联集合查询

    联集合查询相当于SQL中的联表查询。在某些情况下,一些相关的数据需要保存到多个集合中,然后使用某一个字段来进行关联,联集合查询的关键字为“$lookup”,它的语法如下:

    主集合.aggregate{
        [
            {
                "$lookup": {
                    "from":"被查集合名",
                    "localField":"主集合字段",
                    "foreignField":"被查集合字段",
                    "as": "保存查询结果的字段名"
                }
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    为了方便演示,我们给 user 集合和 info 集合分别新增一个 id 和 uid 字段用以关联两个集合。

    // 为 user 集合新增 id 字段
    db.user.updateOne({_id:ObjectId("62e7759f6959971a547354d4")},{"$set":{"id":1}});
    db.user.updateOne({_id:ObjectId("62e7759f6959971a547354d5")},{"$set":{"id":2}});
    db.user.updateOne({_id:ObjectId("62e775a06959971a547354d6")},{"$set":{"id":3}});
    db.user.updateOne({_id:ObjectId("62e775ac6959971a547354d8")},{"$set":{"id":4}});
    db.user.updateOne({_id:ObjectId("62e775ac6959971a547354d9")},{"$set":{"id":5}});
    db.user.updateOne({_id:ObjectId("62e7ac84a617f839c6d097bf")},{"$set":{"id":6}});
    db.user.updateOne({_id:ObjectId("62e7ac84a617f839c6d097c0")},{"$set":{"id":7}});
    
    // 为 info 集合新增 uid 字段
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d2d")},{"$set":{"uid":1}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d2e")},{"$set":{"uid":2}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d2f")},{"$set":{"uid":3}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d30")},{"$set":{"uid":4}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d31")},{"$set":{"uid":5}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d32")},{"$set":{"uid":6}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d33")},{"$set":{"uid":7}});
    db.info.updateOne({_id:ObjectId("62e7df2c475e726c7b533d34")},{"$set":{"uid":8}});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    准备工作完成,我们可以使用联集合查询的语法查询数据看看效果:

    db.user.aggregate(
        [
            {
                "$lookup":{
                    "from":"info",
                    "localField":"id",
                    "foreignField":"uid",
                    "as" : "result"
                }
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    我们看到,result 字段就是我们查询的结果,它就是被关联集合里查询到的数据:

    db.user.aggregate(
        [
            {
                "$lookup":{
                    "from":"info",
                    "localField":"id",
                    "foreignField":"uid",
                    "as" : "result"
                }
            },
            {"$project":{"result":1,"_id":0}},
            {
                "$unwind":"$result"
            },
            {
                "$project":{
                    "name":"$result.name",
                    "date":"$result.hire_date",
                    "score":"$result.score",
                }
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    有了之前的基础,上面的语句也就不难理解了,我们拆解出来 result 字段的数据,发现是符合我们预期的。

    上面我们以 user 集合为基准查看,那如果我们换为以 info 表为基准又是什么样呢?

    db.info.aggregate(
        [
            {
                "$lookup":{
                    "from":"user",
                    "localField":"uid",
                    "foreignField":"id",
                    "as" : "result"
                }
            },
            {
                "$unwind":"$result"
            }
        ]
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    我们看到这里查询出来的数据也是7条,这说明这里的联集合查询实现的是 mysql 中 inner join 的效果。

    本节的内容就到这里了,关于 mongo 的基础操作也就到这里了,下节也是最后一节我们学习怎么优化 mongodb。

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

  • 相关阅读:
    vue3发送验证码倒计时 (防止连点、封装复用)
    低代码引领AI创新:业务解决方案智能化设计
    【树莓派不吃灰】基础篇⑲ 搭建usb摄像头MJPG-streamer图片流监控,支持远程视频监控访问
    程序员就该这样解读《隐秘的角落》
    3D立体相册不过是冷锋蓝plus版 html+css
    sip网络话筒主机SIP桌面式对讲广播主机
    基于Spring Boot项目构建流水线
    第一天 关于项目遇到的问题和缺少的知识点
    30 个数据工程必备的Python 包
    Java基础
  • 原文地址:https://blog.csdn.net/hxj413977035/article/details/126111063