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实现的,如果用别的方式实现的找对应的操作填入参数即可,代码部分因为实际使用中的比较复杂,所以都是写文章时单独整理临时写的,所以可能会存在一些问题。
   
 
