【MongoDB】多级嵌套数组的操作 含Mongo Shell 和 MongoTemplate的增删改细节

本文介绍了在MongoDB中处理嵌套数组的增删改操作,包括MongoShell和MongoTemplate的实践,重点讲解了$[<identifier>]和arrayFilters的使用,以解决只修改特定元素字段的需求。文章提供了一级和二级数组操作的示例,并给出了Java代码实现。

1.前言

最近遇到了一个需求,需要在系统中配置用户的自定义字段,考虑到后续维护的灵活性,选择了使用MongoDB来持久化自定义字段数据,在做这个需求的过程中,遇到了同一个数据中有多层嵌套数组的增删改问题,在网上查阅了大部分的资料说的不是很全,于是在处理好这个需求之后,整理并记录一下处理中使用到的一些技术细节,以供大家参考。

本文包含了一级和二级嵌套数组的操作,篇幅较长,如果只想了解在生产服务中如何应用,可以直接查看目录中的 4.Mongo Template 操作实践

2.数据准备

首先是数据结构准备,这里我处理掉了和公司有关的信息,下面展示的是一个简单的Demo结构,可以看到的是在自定义字段 userDefinedFields 是一个数组类型的数据,表示同一个用户可以有多个自定义字段。自定义字段的类型type如果为 select ,则还会包含下列框的选项字段 options ,也是一个数组,此时就出现了两层的嵌套数组了。

{
   
   
    "_id":1,
    "userId":"1",
    "userDefinedFields":[
        {
   
   
            "key":"111",
            "name":"自定义字段1",
            "type":"input"
        },
        {
   
   
            "key":"222",
            "name":"自定义字段2",
            "type":"select",
            "options":[
                {
   
   
                    "optionKey":"11",
                    "optionValue":"选项1"
                },
                {
   
   
                    "optionKey":"22",
                    "optionValue":"选项2"
                }
            ]
        }
    ]
}

现在遇到的问题就是,不想一个大JSON来对这条数据做全量操作,只想针对数组中的某一个元素中的字段做修改,如何才能实现呢?

3.Mongo Shell操作实践

查询MongoDB的官方文档中与数组更新相关的部分:《Array Update Operators》,可以看到如下的一些操作方式。
在这里插入图片描述
接下来就按照文档的指引,完成下面的操作。

3.1.第一层数组操作

3.1.1.新增元素

userDefinedFields中添加数据,即新建一个自定义字段。可以使用 $push$addToSet,两者的区别是 $addToSet 添加的元素不能在数组中已存在,而$push没有限制,此处用$push演示。

db.user_defined_field.updateMany(
    {
   
   _id:1},
    {
   
   $push:{
   
   "userDefinedFields":{
   
   "key":"333","name":"自定义字段3","type":"input"}}}
);

此时的数据会如下:

{
   
   
    "_id":1,
    "userId":"1",
    "userDefinedFields":[
        {
   
   
            "key":"111",
            "name":"自定义字段1",
            "type":"input"
        },
        {
   
   
            "key":"222",
            "name":"自定义字段2",
            "type":"select",
            "options":[
                {
   
   
                    "optionKey":"11",
                    "optionValue":"选项1"
                },
                {
   
   
                    "optionKey":"22",
                    "optionValue":"选项2"
                }
            ]
        },
        {
   
   
            "key":"333",
            "name":"自定义字段3",
            "type":"input"
        }
    ]
}

3.1.2.修改元素

修改元素需要使用到 $$[],两者的区别在于 $ 只修改条件匹配的第一个元素 $[]是修改条件匹配的全部元素。

// 第一层数组修改
db.user_defined_field.updateMany(
    {
   
   _id:1,"userDefinedFields.type":"input"},
    {
   
   $set:{
   
   "userDefinedFields.$.name":"测试$"}}
);

此时只修改了第一个结果(减少篇幅,后续的数据从数组开始展示,外层的id不展示了):
在这里插入图片描述

3.1.2.1.批量修改元素中的坑

再尝试批量修改元素:

db.user_defined_field.updateMany(
    {
   
   _id:1,"userDefinedFields.type":"input"},
    {
   
   $set:{
   
   "userDefinedFields.$[].name":"测试$[]"}}
);

在这里插入图片描述
如上图所示,typeselect 的元素也被修改了,也就是说"userDefinedFields.type":"input"并没有生效,这显然是不符合要求的。

查阅了MongoDB文档,这种更新需要使用 $[<identifier>] 来标识待查询的条件,$[]具体应该怎么用呢?

3.1.3.使用$[<identifier>]做批量修改

先看一下语法:

db.collectio
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

挥之以墨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值