使用MongoTemplate批量更新内嵌数组元素

原生Mongo从3.6以上可以使用$[]操作符批量修改内嵌数组元素,以下是基于mongoTemplate的封装实现:

/**
 * MonogoDB 更新操作符
 */
@Getter
@AllArgsConstructor
public enum UpdateOperator {
    //
    INC("$inc"),
    SET("$set");

    String code;
}

/**
     * 更新内嵌数组指定元素
     *
     * @param query         更新的文档查询条件
     * @param arrayName     更新的内嵌数组名
     * @param updateMap    对内嵌数组元素不同操作的更新map
     * @param eleFilter 更新内嵌数组元素的过滤条件
     * @return
     */
public UpdateResult updateArrayElement(Criteria query, String arrayName, Map<UpdateOperator, JSONObject> updateMap, Criteria eleFilter){
        BasicDBObject update = new BasicDBObject();
        UpdateOptions updateOptions = new UpdateOptions();

        // 设置$set和$inc等操作符对应的元素更新
        for (UpdateOperator operator : updateMap.keySet()){
            BasicBSONObject eleSetBson = new BasicBSONObject();
            JSONObject eleSetJson = updateMap.get(operator);
            for (String key : eleSetJson.keySet()){
                eleSetBson.put(arrayName.concat(".$[item].").concat(key), eleSetJson.get(key));
            }
            update.put(operator.getCode(), eleSetBson);
        }

        BasicDBObject eleFilterBson = new BasicDBObject();
        Document filter = eleFilter.getCriteriaObject();
        for (String key : filter.keySet()){
            eleFilterBson.put("item.".concat(key), filter.get(key));
        }
        updateOptions.arrayFilters(Lists.newArrayList(eleFilterBson));
        return mongoTemplate.getCollection(tabName).updateMany(
                query.getCriteriaObject(),
                update,
                updateOptions
        );
    }

假设有以下数据,实现将"_id":"id"文档中sex为1的des设为"男",age加2:

{
	"_id":"id",
	"users":[
		{
			"uid":2,
			"sex":1,
			"age":23,
			"des":"",
			"name":"Alex"
		},
		{
			"uid":3,
			"sex":1,
			"age":33,
			"des":"",
			"name":"Bob"
		},
		{
			"uid":4,
			"sex":0,
			"age":20,
			"des":"",
			"name":"Cat"
		},
	]
}
public void demo(){
        Map<UpdateOperator, JSONObject> updateMap = new HashMap<>();
        JSONObject setJson = new JSONObject();
        JSONObject incJson = new JSONObject();
        setJson.put("des", "男");
        incJson.put("age", 2);
        updateMap.put(UpdateOperator.SET, setJson);
		updateMap.put(UpdateOperator.INC, incJson );
        // 批量设置用户的状态
        updateArrayElement(
            Criteria.where("_id").is("id"),
            "users",
            updateMap,
            Criteria.where("sex").is(1)
        );
    }

你可能感兴趣的:(使用MongoTemplate批量更新内嵌数组元素)