SpringBoot整合Mongodb文件資料庫

zhαojh發表於2024-07-08

新增Maven依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置Mongodb連線資訊

spring:
  data:
    mongodb:
      host: 10.30.29.246
      port: 16030
      authenticationDatabase: admin # 登入使用者的認證庫
      database: nrdt
      username: admin
      password: QAZqaz@123321

通用服務(動態集合資料)

以下程式碼實現主要針對集合名稱和欄位都是未知的情況

@Slf4j
@Component
public class MongodbService {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 新增集合(表)
     *
     * @param collName
     */
    public void addCollection(String collName) {
        Assert.notEmpty(collName, "collName");
        boolean bol = mongoTemplate.collectionExists(collName);
        if (!bol) {
            mongoTemplate.createCollection(collName);
        }
    }

    /**
     * 刪除集合(表)
     *
     * @param collName
     */
    public void dropCollection(String collName) {
        Assert.notEmpty(collName, "collName");
        boolean bol = mongoTemplate.collectionExists(collName);
        if (bol) {
            mongoTemplate.dropCollection(collName);
        }
    }

    /**
     * 清空集合資料
     *
     * @param collName
     */
    public void clearCollection(String collName) {
        Assert.notEmpty(collName, "collName");
        boolean bol = mongoTemplate.collectionExists(collName);
        if (bol) {
            mongoTemplate.remove(new Query(), collName);
        }
    }

    /**
     * 修改欄位名稱
     *
     * @param collName
     * @param oldName
     * @param newName
     * @return
     */
    public boolean editField(String collName, String oldName, String newName) {
        Assert.notEmpty(collName, "collName");
        Assert.notEmpty(oldName, "oldName");
        Assert.notEmpty(newName, "newName");
        Query query = new Query();
        Update update = new Update();
        update.rename(oldName, newName);
        UpdateResult result = mongoTemplate.updateMulti(query, update, collName);
        return result.wasAcknowledged();
    }

    /**
     * 刪除指定列
     *
     * @param collName
     * @param field
     */
    public boolean dropField(String collName, String field) {
        Assert.notEmpty(collName, "collName");
        Assert.notEmpty(field, "field");
        Query query = new Query();
        Update update = new Update();
        update.unset(field);
        UpdateResult result = mongoTemplate.updateMulti(query, update, collName);
        return result.wasAcknowledged();
    }

    /**
     * 新增欄位
     *
     * @param collName
     * @param field
     * @return
     */
    public boolean addField(String collName, String field) {
        Assert.notEmpty(collName, "collName");
        Assert.notEmpty(field, "field");
        Query query = new Query();
        query.fields().include(field);
        boolean bol = mongoTemplate.exists(query, collName);
        if(!bol){
            Update update = new Update();
            update.set(field, 0.00d);
            UpdateResult result = mongoTemplate.updateMulti(query, update, collName);
            return result.wasAcknowledged();
        }
        return false;
    }

    /**
     * 新增多個欄位
     *
     * @param collName
     * @param fields
     * @return
     */
    public boolean addFields(String collName, List<String> fields) {
        Assert.notEmpty(collName, "collName");
        Assert.notNull(fields, "fields");
        Update update = new Update();
        boolean status = false;
        for (String field : fields) {
            Query query = new Query();
            query.fields().include(field);
            boolean bol = mongoTemplate.exists(query, collName);
            if(!bol){
                update.set(field, 0.00d);
                status = true;
            }
        }
        if(status){
            UpdateResult result = mongoTemplate.updateMulti(new Query(), update, collName);
            return result.wasAcknowledged();
        } else {
            return false;
        }
    }

    /**
     * 批次新增行資料
     *
     * @param collName
     * @param jsonArray
     */
    public void insert(String collName, JSONArray jsonArray) {
        Assert.notEmpty(collName, "collName");
        Assert.notNull(jsonArray, "jsonArray");
        mongoTemplate.insert(jsonArray, collName);
    }

    /**
     * 批次插入
     * insert: 可以一次性插入一整個列表,不允許插入已存在的主鍵
     * save:   需要遍歷列表,進行一條一條的資料插入,主鍵存在則是修改
     * @param collName
     * @param list
     */
    public void insert(String collName, List<Document> list) {
        Assert.notEmpty(collName, "collName");
        Assert.notNull(list, "list");
        mongoTemplate.insert(list, collName);
    }

    /**
     * 修改行資料
     *
     * @param collName
     */
    public void edit(String collName, JSONObject jsonObject) {
        Assert.notEmpty(collName, "collName");
        Assert.notNull(jsonObject, "jsonObject");
        mongoTemplate.save(jsonObject, collName);
    }

    /**
     * 刪除行資料
     *
     * @param collName
     */
    public boolean remove(String collName, String[] ids) {
        Assert.notEmpty(collName, "collName");
        Assert.notNull(ids, "ids");
        Query query = new Query(Criteria.where(MongoConstants.ID_COLUMN).in(ids));
        DeleteResult result = mongoTemplate.remove(query, collName);
        return result.wasAcknowledged();
    }

    /**
     * 抽樣查詢
     * @param search
     * @return
     */
    public List<Document> getListSample(SearchVo search){
        List<AggregationOperation> list = new ArrayList<>();
        list.add(Aggregation.sample(search.getSampleSize()));
        if(StrUtil.isNotEmpty(search.getColumns())){
            list.add(Aggregation.project(search.getColumns().split(",")));
        }
        Aggregation aggregation = Aggregation.newAggregation(list);
        return mongoTemplate.aggregate(aggregation, search.getCollName(), Document.class).getMappedResults();
    }

    /**
     * 查詢樣本時間的上下限
     * @param collName
     * @return
     */
    public Map<String, Object> getTimes(String collName){
        long startTime = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        Assert.notEmpty(collName, "collName");
        List<AggregationOperation> list = new ArrayList<>();
        list.add(Aggregation.project(MongoConstants.TIME_COLUMN));
        list.add(Aggregation.group().min(MongoConstants.TIME_COLUMN).as("minTime").max(MongoConstants.TIME_COLUMN).as("maxTime"));
        Aggregation aggregation = Aggregation.newAggregation(list);
        Document doc = mongoTemplate.aggregate(aggregation, collName, Document.class).getRawResults();
        if(doc != null){
            if(Convert.toInt(doc.get("ok")) == 1){
                List<Document> results =  doc.get("results", List.class);
                if(results != null && results.size() > 0){
                    Document obj = results.get(0);
                    if(obj != null){
                        map.put("minTime", obj.getLong("minTime"));
                        map.put("maxTime", obj.getLong("maxTime"));
                    }
                }
            }
        }
        if(CollUtil.isEmpty(map)){
            map.put("minTime", null);
            map.put("maxTime", null);
        }
        log.info("查詢樣本上下限時間,耗時:{}秒", (System.currentTimeMillis() - startTime)/1000);
        return map;
    }
    /**
     * 分頁查詢表資料
     *
     * @param search
     * @return
     */
    public TableDataInfo getPage(SearchInput search) {
        List<JSONObject> list = new ArrayList<>();
        Query query = getQuery(search);
        long count = mongoTemplate.count(query, search.getCollName());
        if (count > 0L) {
            if (StrUtil.isEmpty(search.getSort())) {
                // 預設根據時間排序
                search.setSort(MongoConstants.TIME_COLUMN);
            }
            // 分頁:跳過前skip個文件,返回接下來的pageSize個文件
            int skip = (search.getPageNum() - 1) * search.getPageSize();
            query = query.with(Sort.by(search.getSort()).ascending()).skip(skip).limit(search.getPageSize());
            list = mongoTemplate.find(query, JSONObject.class, search.getCollName());
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(list);
        rspData.setMsg("查詢成功");
        rspData.setTotal(count);
        return rspData;
    }

    /**
     * 根據條件查詢資料量
     *
     * @param search
     * @return
     */
    public long getCount(SearchInput search) {
        Query query = getQuery(search);
        return mongoTemplate.count(query, search.getCollName());
    }

    /**
     * 分頁查詢集合的資料
     *
     * @param search
     * @return
     */
    public List<Document> getListDoc(SearchInput search) {
        Query query = getQuery(search);
        if (StrUtil.isNotEmpty(search.getSort())) {
            query = query.with(Sort.by(search.getSort()).ascending());
        }
        int skip = (search.getPageNum() - 1) * search.getPageSize();
        query = query.skip(skip).limit(search.getPageSize());
        return mongoTemplate.find(query, Document.class , search.getCollName());
    }

    /**
     * 隨機查詢一條資料
     * @param collName
     * @return
     */
    public JSONObject getOne(String collName){
        Query query = new Query();
        query = query.limit(1);
        return mongoTemplate.findOne(query, JSONObject.class, collName);
    }

    public Query getQuery(SearchInput search) {
        Criteria criteria = new Criteria();
        List<Criteria> criteriaList = new ArrayList<>();
        if (StrUtil.isNotEmpty(search.getBeginTime())) {
            criteriaList.add(Criteria.where(MongoConstants.TIME_COLUMN).gte(Convert.toLong(search.getBeginTime())));
        }
        if (StrUtil.isNotEmpty(search.getEndTime())) {
            criteriaList.add(Criteria.where(MongoConstants.TIME_COLUMN).lte(Convert.toLong(search.getEndTime())));
        }
        if (criteriaList.size() > 0) {
            criteria.andOperator(criteriaList);
        }
        Query query = new Query(criteria);
        if (StrUtil.isNotEmpty(search.getColumns())) {
            query.fields().include(search.getColumns().split(","));
        }
        if(StrUtil.isNotEmpty(search.getExclude())){
            query.fields().exclude(search.getExclude().split(","));
        }
        return query;
    }

    /**
     * 根據條件複製一個新的集合資料
     * @param search
     */
    // @Async("threadPoolTaskExecutor")
    public void copyCollection(SearchCopy search) {
        long startTime = System.currentTimeMillis();
        log.info("開始把集合[{}]結果輸出到另一個集合[{}]...", search.getCollName(), search.getNewId());
        clearCollection(search.getNewId());
        List<AggregationOperation> list = new ArrayList<>();
        if(StrUtil.isNotEmpty(search.getColumns())){
            list.add(Aggregation.project(search.getColumns().split(",")));
        }
        if(StrUtil.isNotEmpty(search.getBeginTime())){
            list.add(Aggregation.match(new Criteria(MongoConstants.TIME_COLUMN).gte(Convert.toLong(search.getBeginTime()))));
        }
        if(StrUtil.isNotEmpty(search.getEndTime())){
            list.add(Aggregation.match(new Criteria(MongoConstants.TIME_COLUMN).lte(Convert.toLong(search.getEndTime()))));
        }
        list.add(Aggregation.out(search.getNewId()));
        Aggregation aggregation = Aggregation.newAggregation(list);
        mongoTemplate.aggregateStream(aggregation, search.getCollName(), Document.class);
        log.info("結果輸出完成,耗時:{}秒", (System.currentTimeMillis() - startTime)/1000);
    }
}

MongoTemplate增強版

使用手冊:https://loser.plus/

使用MyBatisPlus的方式,優雅的操作MongoDB。

這種方式是如同Mysql表結構一樣,已知集合名稱和欄位名稱,預先定義好欄位型別,自動與Mongodb進行關係對映。

相關文章