MongoDB——upsert

MongoDB——upsert

功能需求:插入数据时,根据库中原有数据中一个或多个字段判断当前插入的数据是否存在,存在则执行更新,不存在则执行插入。
MongoDB依赖为spring-boot-starter-data-mongodb默认版本
思路:MongoDB有提供更新或插入的API,update中将upsert参数的值设置为true即可实现不存在数据执行插入,判断存在的数据则需要将用来当做判断条件的字段建立唯一索引,多个字段需要建立复合唯一索引。

官方文档说明:

db.collection.updateMany(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)

源码:

/**
     * Update all documents in the collection according to the specified arguments.
     *
     * @param filter        a document describing the query filter, which may not be null.
     * @param update        a document describing the update, which may not be null. The update to apply must include only update operators.
     * @param updateOptions the options to apply to the update operation
     * @return the result of the update many operation
     * @throws com.mongodb.MongoWriteException        if the write failed due some other failure specific to the update command
     * @throws com.mongodb.MongoWriteConcernException if the write failed due being unable to fulfil the write concern
     * @throws com.mongodb.MongoException             if the write failed due some other failure
     * @mongodb.driver.manual tutorial/modify-documents/ Updates
     * @mongodb.driver.manual reference/operator/update/ Update Operators
     */
     
    UpdateResult updateMany(Bson filter, Bson update, UpdateOptions updateOptions);

    @Override
    public UpdateResult updateMany(final Bson filter, final Bson update, final UpdateOptions updateOptions) {
        return executeUpdate(null, filter, update, updateOptions, true);
    }

项目代码:

//筛选条件
    public Document filter(Map<String, Object> map){
        List<Map<String,Object>> listMap;
        Document filter = new Document();
        if (map.containsKey("queryType") && map.get("queryType").equals("or")){
            if (map.containsKey("data") && map.get("data")instanceof List){
                listMap = (List<Map<String, Object>>) map.get("data");
                filter = new Document("$or", listMap);
            }
            if (map.containsKey("filter") && map.get("filter")instanceof List){
                listMap = (List<Map<String, Object>>) map.get("filter");
                filter = new Document("$or", listMap);
            }
        }else {
            if (map.containsKey("data") && map.get("data")instanceof List) {
                listMap = (List<Map<String, Object>>) map.get("data");
                filter = new Document("$and", listMap);
            }
            if (map.containsKey("filter") && map.get("filter")instanceof List){
                listMap = (List<Map<String, Object>>) map.get("filter");
                filter = new Document("$and", listMap);
            }
        }
        return filter;
    }

    //更新
    @Override
    public Map updateManyByCollectionName(Map<String, Object> map) {
        //需改内容
        List<Map<String, Object>> list;
        Map<String,Object> set = new HashMap<>();
        if (map.containsKey("set") && map.get("set")instanceof Map){
            set = (Map<String, Object>) map.get("set");
        }else if (map.containsKey("data") && map.get("data")instanceof List){
            list = (List<Map<String, Object>>) map.get("data");
            for (int i=0;i<list.size();i++){
                set.putAll(list.get(i));
            }
        }
        Document document = new Document("$set", new Document(MongoDBUtil.setParameter(set)));
        //记录存在执行更新,不存在执行新增
        UpdateResult updateResult = getDBCollection(map.get("collectionName").toString()).updateMany(filter(map), document,new UpdateOptions().upsert(true));
        return new HashMap<String, Object>(){{put("code","200");put("message","匹配数"+updateResult.getMatchedCount()+";修改数"+updateResult.getModifiedCount());}};
    }

记录一个偷懒导致的坑
把filter(过滤条件)参数和set(待更新)参数合并用,upsert的插入操作能执行,执行更新时会报重复的唯一索引异常( E11000 duplicate key error collection)。
最后看官方文档发现,对upsert参数作说明时提到filter参数必须被唯一索引。
(To avoid multiple upserts, ensure that the filter fields are uniquely indexed.)
看文档要仔细!!!

官方文档:
http://docs.mongodb.org/manual/core/write-operations-atomicity/
http://docs.mongodb.org/manual/core/index-unique/#index-type-unique

猜你喜欢

转载自blog.csdn.net/RookieCode/article/details/106384041