mongodb 子集操作汇总(较详细,附带springBoot中的操作)

  • Post author:
  • Post category:其他


mongodb中子集的操作也算是很经典的一部分,但是最近有用到找的的资料都偏简单,所以问题解决后顺便整理记录下mongodb子集的所有操作。


全文示例结构:


collection: test

{

_id:ObjectId('62fc3dd6babacc41da59a94b'),

date:'2022-08-18',

child:[
{childId:1,type:1,name:'测试1'},
{childId:11,type:1,name:'测试11'},
{childId:2,type:2,name:'测试2'}
]

}



1.子集新增


1)整体覆盖的形式新增

这种比较简单,就是将整个记录取出,然后对子集的文档进行整体替换然后更新记录,或者用更新语句对整个文档进行更新,这里如果会有多线程的话很容易出现脏读幻读不可重复读的问题,所以如果是子集操作频繁且复杂不建议使用,后续的修改和删除都有同样的问题,所以均省略。



2)子集单个文档内部操作的方式新增。


关键操作:$push(单个)、$pushAll(多个)、$addToSet(单个多个都可以,会去重)

语句:db.collection.update(query,update,options)

update内容:{$addToSet:{clo:{}}}、{$addToSet:{col:{$each:[]}}}、{$push:{clo:{}}}、{$push:{clo:[]}}

注释:query–条件,update–更新内容,options–各种配置项有multi等

示例($addToSet单个多个语法会不同,所以以$addToSet举例,其他两个参照addToSet的单个添加):

新增一条数据到child中:

db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b')},{$addToSet:{child:{childId:3,type:3,name:'测试3'}}});

spring boot

//条件
             //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                Query upQuery = Query.query(criteria);

                //更新内容
               //这里object意思是单个对象
                Update update = new Update().addToSet("child",object);

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");

一定要注意,这里就算传入数组也会被当成一条数据更新进去,所以要多条的话一定要用到$each关键字。

新增多条数据到child中

db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b')},{$addToSet:{child:{$each:[{childId:3,type:3,name:'测试3'},{childId:4,type:4,name:'测试4'}]}}});

spring boot

             //条件
             //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                Query upQuery = Query.query(criteria);

                //更新内容
               //这里arry意思是数组,需要什么对象放进去即可
                Update update = new Update().addToSet("child").each(array);

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");

$push、$pushALL和$addToSet区别就是$addToSet会去重,根据自己的需要选择使用,如果不需要去重用$push、$pushALL,因为不匹配肯定快些.


2.子集内容修改

关键操作:$set,字段部分 col .$.childCol–只修改匹配到的第一条, col .$[queryName].childCol—修改queryName匹配到的全部

这个如果对子集字段的修改不太熟悉的话,可能比较难看懂,直接看示例会容易理解些

语句:db.collection.update(query,update,options)

示例

将child中type = 1的第一条数据的name字段改成 “测试01”

//这里注意子集字段在查询条件直接是 父子段.子集字段 的形式,修改关键字是 父子段.$.子集字段
db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b'),child.type:1},{$set:{child.$.name:"测试01"}})

spring boot中

      //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                criteria.and("child.type").is(1);
                Query upQuery = Query.query(criteria);

                //更新内容
                Update update = new Update();
                update.set("child.$.name","测试01");

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");


将child中type = 1的所有数据的的name字段改成 “测试01”

//这里的 all 是自定义的,修改时会根据all标记的条件对子集进行筛选并修改
db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b'),all.type:1},{$set:{child.$[all].name:"测试01"}})

spring boot中

 //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                criteria.and("all.type").is(1);
                Query upQuery = Query.query(criteria);

                //更新内容
                Update update = new Update();
                update.set("child.$[all].name","测试01");

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");

这里我只放了一个条件type,如果还需要别的条件直接在all条件下面补充即可,比如讲type = 1且 chidId = 1的name改为“测试01” 那条件中就是 :

{_id:ObjectId(’62fc3dd6babacc41da59a94b’),all.type:1,all.childId:1}


3.子集删除

关键操作:$pull,$pullAll

语句:db.collection.update(query,update,options),针对子集的操作都是用父记录的修改操作完成。

示例中都以$pull进行示例,$pullAll使用用完全匹配的删除多个,子集只有单个字段且一次性删除多个的时候用pullAll会方便很多,语法和$pull一致,只不过传的参数是数组。


1)完全匹配型删除

//删除数据{childId:1,type:1,name:'测试1'}
db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b')},{$pull:{child:{childId:1,type:1,name:'测试1'}}});

spring boot中

 //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                Query upQuery = Query.query(criteria);

                //更新内容
                Update update = new Update();
                //这里object是要删除的对象
                update.pull("child",object)

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");


2)条件匹配型删除

//删除ID 为 62fc3dd6babacc41da59a94b的数据,child子集中type = 1 和 type = 2 的所有子集数据
db.test.update({_id:ObjectId('62fc3dd6babacc41da59a94b')},{$pull:{child:{type:{$in[1,2]}}}});

spring boot中

               //这里的条件用的是ID,具体情况根据自己的需要来加
                Criteria criteria= new Criteria();
                criteria.and("_id").is(new ObjectId(""));
                Query upQuery = Query.query(criteria);

                //更新内容
                Update update = new Update();
               //这里的types就是type类型的数组或列表,我这里写demo偷懒了没有单独定义,实际使用需 
                 //要定义
                BasicDBObject  basicDBObject = new BasicDBObject("type",new 
                BasicDBObject("$in",types));
                //这里object是要删除的对象
                update.pull("child",basicDBObject )

               //这里用的是允许更新多条,具体只更新一条还是多条根据自己的情况来就oK
                mongoTemplate.updateMulti(upQuery,update,"test");


4.子集条件查询

如果是单个的子集条件则比较简单,直接 查询字段写col.childCol即可,即,父字段.子集字段,多个的时候就会发现第二个是失效的,这时候就要用到

$elemMatch

关键字。单字段查询较简单,如果不会的话找官方文档或者找帖子很多,这里列举下多字段的查询。

示例

查询chil中 type = 1 和 childId = 11的数据(这里查出来是父集的一条记录,不是单条的子集记录,单条的子集记录目前我这里没有使用场景所以还未解锁,以后如果解锁了再补充)

db.test.find({child:{$elemMatch:{type:1,childId:11}}});

spring boot中

               //用BasicDBObject来组成条件里面的json
                BasicDBObject  basicDBObject = new BasicDBObject();
                basicDBObject.append("type",1);
                basicDBObject.append("childId",11);
              //最终的查询条件
                Criteria criteria= new Criteria();
                criteria.and("child").is(new BasicDBObject("$elemMatch",basicDBObject));
                Query query = Query.query(criteria);
               //这里test是定义的实体对象,没有展示出来
                List<test> res = mongoTemplate.find(query ,test.class,"test");


总结 :


这里列举的是简单到中等复杂成都的操作,整体需要对mongodb基础的语句比较熟悉,主要是uodate操作中的针对array类型的修改器的使用,如果有不懂的,直接查找相关关键字的用法就可以比较明白,另外条件还可以用表达式,只要研究清楚基础的机构,传值部分还是有很多可能。spring boot中的我用的是 mongoTemplate实现的,如果用别的方式实现的找对应的操作填入参数即可,代码部分因为实际使用中的比较复杂,所以都是写文章时单独整理临时写的,所以可能会存在一些问题。



版权声明:本文为qq_37721238原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。