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. 数据转换

    我们前面学习了使用{“字段名”: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}}
    ]
);

在这里插入图片描述

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

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

// 抽取嵌套字段
db.user.aggregate(
    [
        {"$project":{"name":"$friend.name","age":"$friend.age"}}
    ]
);

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

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

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

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

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

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

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

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

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不务正业的攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值