如何使用 spring 在 mongodb 中进行智能更新?

How to do smart updates in mongodb using spring?

是否有更新 mongo 数据库中数据的智能优化方法?我现在以下面的方式做,但想用更少的数据库调用来做。

@Transactional
public void modifyParticipant(String id, String roomId, updates) {
    Conference conference = conferenceRepository.findParticipantsByRoomId(roomId);
    for(Participant participant : conference.getParticipants()){
        if(participant.getId().equals(id)){
            //modify the participant
            break;
        }
    }
    conference.updateTime();
    conferenceRepository.save(conference);
    }

我尝试了以下方法,但从未成功,因为查询总是获取参与者数组,即使我试图只获取一个与 id 匹配的参与者。并且由于数组更新失败。

尝试

@Override
public void modifyParticipants(String id, String roomId, Map<String, String> map) {

    Query query = new Query();
    query.addCriteria(new Criteria().andOperator(Criteria.where("_id").is(roomId), Criteria.where("participants").elemMatch(Criteria.where("_id").is(id))));
    Conference conference = operations.findOne(query, Conference.class);
    String temp;
    Update update = new Update();
    if((temp = map.get("firstName")) != null){
        update.push("participants.$.firstName",temp);
    }
    if((temp = map.get("lastName")) != null){
        update.push("participants.$.lastName", temp);
    }
    if((temp = map.get("avatarUrl")) != null){
        update.push("participants.$.avatarUrl",temp);
    }
    if((temp = map.get("state")) != null){
        update.push("participants.$.state", temp);
    }
    if((temp = map.get("avState")) != null){
        update.push("participants.$.avState", temp);
    }
    operations.updateFirst(query, update, Conference.class);
}

数据结构

{ 
    "_id" : "f9091ed9-c828-4b52-b1c3-44e42f719694", 
    .....,
    "participants" : [
        {
            "_id" : "6b49b373-1e61-4c98-a703-c1c2bc4da0e2", 
            "deviceId" : "7F55271D-946C-44B0-BFAC-461447021762", 
            "avatarUrl" : "", 
            "firstName" : "ddd", 
            "lastName" : "qwr", 
            "state" : "REMOVED", 
            "about" : "", 
            "avState" : "OFFLINE", 
            "version" : NumberInt(0), 
            "timeCreated" : ISODate("2015-11-09T00:36:41.585+0000")
        }, 
        {
            "_id" : "48f32b8e-3c40-48c2-96fa-74e93c388cd1", 
            "deviceId" : "7F55271D-946C-44B0-BFAC-461447021762", 
            "avatarUrl" : "", 
            "firstName" : "wer", 
            "lastName" : "wrf", 
            "state" : "ONLINE", 
            "about" : "", 
            "avState" : "OFFLINE", 
            "version" : NumberInt(0), 
            "timeCreated" : ISODate("2015-11-09T00:37:24.574+0000")
        }
    ]
}

理想情况下,您会希望获得等同于以下更新操作的 mongo shell,该操作使用 $set operator with the $ positional 运算符来标识数组中要更新的元素,而无需明确指定元素在数组中的位置。这意味着在更新语句的查询端匹配数组元素的任何条件将只匹配找到的第一个数组索引:

db.conference.update(
    {
        "_id": "f9091ed9-c828-4b52-b1c3-44e42f719694",
        "participants._id": "6b49b373-1e61-4c98-a703-c1c2bc4da0e2"
    },
    {
        "$set": {
            "participants.$.firstName": "foo",
            "participants.$.lastName": "bar"
        }
    }
)

Spring 数据 MongoDB 等效示例如下:

Query query = new Query(new Criteria().andOperator(
    Criteria.where("_id").is("f9091ed9-c828-4b52-b1c3-44e42f719694"),
    Criteria.where("participants._id").is("6b49b373-1e61-4c98-a703-c1c2bc4da0e2"));

Update update = new Update();
update.set("participants.$.firstName", "foo");
update.set("participants.$.lastName", "bar");
mongoTemplate.updateFirst(query, update, Conference.class);