MongoDB结构文档多层次查询及更新

本文详细介绍在SpringDataMongodb中如何实现对mongoDB的深层次查询及更新操作,包括使用mongoTemplate接口API进行复杂文档结构的处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文记录Spring Data Mongodb中对mongoDB查询及更新的实现.


使用场景

mongoDB中文档会具有较深的深度,在通过mongoTemplate进行处理时,需要注意使用的语法.本文介绍两种场景:深层次查询及更新

技术点

  • mongoDB语法
  • mongoTemplate接口API

mongoDB文档展示

{
    "_id" : ObjectId("5d5684ae1599021e848d6736"),
    "vehicleId" : "AP_4028b2b64fb20697014fdf7f65e44346",
    "list" : [ 
        {
            "groupName" : "发动机系统",
            "groupCode" : "1000",
            "programs" : {
                "vehicleId" : "AP_4028b2b64fb20697014fdf7f65e44346",
                "groupCode" : "1000",
                "list" : [ 
                    {
                        "baseItemName" : "清洗喷油嘴",
                        "baseItemCode" : "QX040001",
                        "itemDesc" : "20000km或24个月/次",
                        "judge" : "1"
                    }, 
                    {
                        "baseItemName" : "润滑系统清洁养护",
                        "baseItemCode" : "QX010001",
                        "itemDesc" : "5000km/次",
                        "judge" : "0"
                    }, 
                    {
                        "baseItemName" : "清洗节气门",
                        "baseItemCode" : "QX020001",
                        "itemDesc" : "20000km或24个月/次",
                        "judge" : "0"
                    }, 
                    {
                        "baseItemName" : "清洗进气系统",
                        "baseItemCode" : "QX010002",
                        "itemDesc" : "20000km/次",
                        "judge" : "0"
                    }, 
                    {
                        "baseItemName" : "火花塞",
                        "baseItemCode" : "BY036055",
                        "judge" : "0"
                    }
                ]
            }
        }, 
        {
            "groupName" : "常规保养",
            "groupCode" : "6000"
        }
    ],
    "_class" : "MaintenanceClassificationRespResult"
}

实现代码:深层次查询

深层次查询(方式一):

// 通过构造函数andOperator()连接and条件,通过elemMatch()指定子级节点
Query query = Query.query(new Criteria().andOperator(Criteria.where("vehicleId").is(vehicleId), Criteria.where("list").elemMatch(Criteria.where("groupCode").is(groupCode))));

// findOne()仅返回匹配的第一个文档,此处需注意返回的为整个文档,若需要指定返回内容,需要使用原生API,findOne()第三个入参为文档表名
MaintenanceClassificationRespResult result = mongoTemplate.findOne(query, MaintenanceClassificationRespResult.class, IEasyepcCode.EASYEPC_MONGODB_325021_325031);


深层次查询(方式二):

// 通过.的形式指定子级节点
Query query = new Query(Criteria.where("vehicleId").is(vehicleId).and("list.groupCode").is(groupCode));


深层次查询(方式三):

此处可以参考博文:学习MongoDB四:MongoDB查询

补充在mongoDB中通过正则表达式实现like查询的方式

Query query = new Query(Criteria.where("licenseNo").regex("^.*" + licenseNo + ".*$").and("storeId").is(storeId));
        List<QueryEnquiryListResp.QueryEnquiryListForm> result = mongoTemplate.find(query, QueryEnquiryListResp.QueryEnquiryListForm.class, IUnderwriteCode.UNDERWRITE_MONGODB_ENQUIRY);

实现代码:深层次更新

深层次更新:

@Transactional(rollbackFor = Exception.class)
public void updateJudgeForMaintenanceClassificationList(String vehicleId, String groupCode, String baseItemCode) {
    /*
     * 由于MongoDB不支持多层占位更新,且占位符必须位于第一个位置,所以需要通过代码逻辑确认除第一层外的数组下标
     * 需要先查询原两层结构
     */
    MaintenanceClassificationRespResult tempResult = queryMaintenanceClassificationByMongoDB(MaintenanceClassificationReqModel
            .builder().vehicleId(vehicleId).build());
    if (!Objects.isNull(tempResult)) {
        List<MaintenanceClassificationRespList> list = tempResult.getList();
        for (int i = 0; i < list.size(); i++) {
            MaintenanceClassificationRespList data = list.get(i);
            if (groupCode.equals(data.getGroupCode())) {
                // 保养项目分类一致,更新其下保养项目明细
                if (!Objects.isNull(data.getPrograms()) && data.getPrograms().getList().size() > 0) {
                    for (int j = 0; i < data.getPrograms().getList().size(); j++) {
                        MaintenanceProgramRespList dataDetail = data.getPrograms().getList().get(j);
                        if (baseItemCode.equals(dataDetail.getBaseItemCode())) {
                            // 确认二层数据下标
                            Query query = Query.query(Criteria.where("vehicleId").is(vehicleId).and("list.programs.list.baseItemCode").is(baseItemCode));
                            Update update = new Update();
                            // 此处i可以替换为$
                            update.set("list." + i + ".programs.list." + j + ".judge", IEasyepcCode.JUDGE_1);
                            UpdateResult updateResult = mongoTemplate.updateFirst(query, update, IEasyepcCode.EASYEPC_MONGODB_325021_325031);
                            log.info("mongoDB更新文档结果:{}", updateResult.toString());
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
}


深层次更新:

@Transactional(rollbackFor = Exception.class)
public void updateJudgeForStructuralQueryList(String vehicleId, String partGroupId) {
    // 存入mongoDB的数据id会自动转换为_id,使用实体接收没有问题,但是查询或更新时,需要使用_id
    Query query = Query.query(new Criteria().andOperator(Criteria.where("vehicleId").is(vehicleId), Criteria.where("partGroupList").elemMatch(Criteria.where("_id").is(partGroupId))));
    Update update = new Update();
    update.set("partGroupList.$.judge", IEasyepcCode.JUDGE_1);
    UpdateResult updateResult = mongoTemplate.updateFirst(query, update, IEasyepcCode.EASYEPC_MONGODB_221001);
    log.info("mongoDB更新文档结果:{}", updateResult.toString());
}

备注

Spring Data Mongodb默认不开启事务,若果需要开启,可以参考Spring Data Mongodb事务管理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值