Spring Boot 项目中使用 MongoDB

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

首先为项目添加 MongoDB 支持。

Gradle:

compile("org.springframework.boot:spring-boot-starter-data-mongodb:2.0.5.RELEASE")
compile("org.mongodb:mongo-java-driver:3.6.4")

Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.6.4</version>
</dependency>

MongoTools 类:

package com.charles.testlibrary.util;

import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MongoTools {

  // mongo环境变量
  private static String host;
  private static String port;
  private static String dbname;
  private static String username;
  private static String password;

  public static String getHost() {
    return host;
  }

  @Value("${spring.data.mongodb.host}")
  public void setHost(String host) {
    MongoTools.host = host;
  }

  public static String getPort() {
    return port;
  }

  @Value("${spring.data.mongodb.port}")
  public void setPort(String port) {
    MongoTools.port = port;
  }

  public static String getDbname() {
    return dbname;
  }

  @Value("${spring.data.mongodb.database}")
  public void setDbname(String dbname) {
    MongoTools.dbname = dbname;
  }

  public static String getUsername() {
    return username;
  }

  @Value("${spring.data.mongodb.username}")
  public void setUsername(String username) {
    MongoTools.username = username;
  }

  public static String getPassword() {
    return password;
  }

  @Value("${spring.data.mongodb.password}")
  public void setPassword(String password) {
    MongoTools.password = password;
  }

  private static MongoClient client = null;
  private static MongoDatabase db = null;
  private static MongoCollection collection;

  public MongoTools() {
  }

  /**
   * 获取数据库.
   * @return
   */
  public static MongoDatabase getDb() {
    try {
      if (client == null) {
        init();
      }
      //连接到数据库
      db = client.getDatabase(dbname);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return db;
  }

  private static void init() {
    System.out.println("com.mongodb.client.MongoCollection");
    ServerAddress sa = new ServerAddress(host, Integer.parseInt(port));
    List<ServerAddress> sas = new ArrayList<>();
    sas.add(sa);
    MongoCredential mc = MongoCredential.createCredential(username, dbname, password.toCharArray());
    List<MongoCredential> mcs = new ArrayList<>();
    mcs.add(mc);
    //连接服务
    client = new MongoClient(sas, mcs);
  }

  /**
   * 建立连接.
   * @param collectionName 数据库
   * @return
   */
  public static MongoCollection getCollection(String collectionName) {
    getDb();
    collection = db.getCollection(collectionName);
    return collection;
  }
}

MongoService 类:

package com.charles.testlibrary.core;


import com.mongodb.MongoNamespace;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Collation;
import com.charles.testlibrary.util.MongoTools;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;

import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapreduce.GroupBy;
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;


@Service
public class MongoService {

    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * 根据key/value计算符合条件的数据数量.
     *
     * @param provalues      value
     * @param collectionName 集合名
     */
    public long countBy(String[] prokeys, Object[] provalues, String collectionName) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        Criteria criteria = new Criteria();
        Criteria[] criterias = new Criteria[prokeys.length];
        for (int i = 0; i < prokeys.length; i++) {
            criterias[i] = Criteria.where(prokeys[i].toString()).is(provalues[i]);
        }
        criteria.andOperator(criterias);
        query.addCriteria(criteria);
        long result = mongoTemplate.count(query, collectionName);
        return result;
    }

    /**
     * 查询大于指定条件的数据量.
     *
     * @param prokeys           key
     * @param provalues         value
     * @param greaterThanKeys   大于条件的key
     * @param greaterThanValues 大于条件的value
     * @param collectionName    集合名
     */
    public long countByGt(String[] prokeys, Object[] provalues,
                          String[] greaterThanKeys,
                          Object[] greaterThanValues, String collectionName) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (int i = 0; i < prokeys.length; i++) {
            query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
        }
        for (int i = 0; i < greaterThanKeys.length; i++) {
            query.addCriteria(Criteria.where(greaterThanKeys[i]).gt(greaterThanValues[i]));
        }
        return mongoTemplate.count(query, collectionName);
    }

    /**
     * 根据key/value查找符合条件的一条数据.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public Map findOne(String[] prokeys, Object[] provalues, String collectionName,
                       String orderBy, Integer order) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        Map m = new HashMap<>();
        Document doc = new Document();
        for (int i = 0; i < prokeys.length; i++) {
            if (i == 0) {
                doc.put(prokeys[i], provalues[i]);
            } else {
                doc.append(prokeys[i], provalues[i]);
            }
        }
        Document sort = new Document();
        if (orderBy != null) {
            sort = new Document(orderBy, order);
        }
        FindIterable iter = coll.find(doc).skip(0).limit(1).sort(sort);
        MongoCursor cursor = iter.iterator();
        if (cursor.hasNext()) {
            m = (Map) cursor.next();
            m.remove("_id");
        }
        return m;
    }

    /**
     * 根据key/value获取bean.
     *
     * @param querys         key/value
     * @param collectionName 集合名
     */
    public Object findOne(Map<String, Object> querys, String collectionName, Class clazz) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (Map.Entry e : querys.entrySet()) {
            query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
        }
        return mongoTemplate.findOne(query, clazz, collectionName);
    }

    /**
     * 根据key/value获取bean.
     *
     * @param querys         key/value
     * @param collectionName 集合名
     */
    public <T> T findEntity(Map<String, Object> querys, String collectionName, Class<T> clazz) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (Map.Entry e : querys.entrySet()) {
            query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
        }
        return mongoTemplate.findOne(query, clazz, collectionName);
    }

    /**
     * 根据key/value查找符合条件的一条数据(取出指定字段).
     *
     * @param prokeys        key
     * @param provalues      value
     * @param includeFields  指定字段集合
     * @param collectionName 集合名
     */
    public Map findOneFilterFeilds(String[] prokeys, Object[] provalues, String[] includeFields,
                                   String collectionName) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        Map m = new HashMap<>();
        Document doc = new Document();
        Document filter = new Document();
        for (int i = 0; i < prokeys.length; i++) {
            if (i == 0) {
                doc.put(prokeys[i], provalues[i]);
            } else {
                doc.append(prokeys[i], provalues[i]);
            }
        }
        for (int i = 0; i < includeFields.length; i++) {
            filter.append(includeFields[i], true);
        }
        FindIterable iter = coll.find(doc).projection(filter).skip(0).limit(1);
        MongoCursor cursor = iter.iterator();
        if (cursor.hasNext()) {
            m = (Map) cursor.next();
            m.remove("_id");
        }
        return m;
    }

    /**
     * 指定key/value分页取出数据.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param skip           跳过前面n条数据
     * @param size           取m条数据
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public List<Map<String, Object>> findByPage(String[] prokeys, Object[] provalues,
                                                String collectionName,
                                                int skip, int size, String orderBy, Integer order) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        List<Map<String, Object>> list = new ArrayList<>();
        Document doc = new Document();
        if (prokeys != null && provalues != null) {
            for (int i = 0; i < prokeys.length; i++) {
                doc.append(prokeys[i], provalues[i]);
            }
        }
        long totalCount = coll.count();
        FindIterable iter = coll.find(doc).skip(skip).limit(size).sort(new Document(orderBy, order));
        MongoCursor cursor = iter.iterator();
        while (cursor.hasNext()) {
            Map m = (Map) cursor.next();
            m.remove("_id");
            list.add(m);
        }
        return list;
    }

    /**
     * 指定key/value分页取出数据.
     *
     * @param filter         筛选条件
     * @param collectionName 集合名
     * @param skip           跳过前面n条数据
     * @param size           取m条数据
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public Map<String, Object> findByPage(Map<String, Object> filter, Map<String, Object> childFilter,
                                          String collectionName, int skip, int size,
                                          String orderBy, Integer order) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        List<Map<String, Object>> list = new ArrayList<>();
        Document doc = new Document();
        List<Document> docList = new ArrayList<Document>();
        Set<String> keySet = filter.keySet();
        for (String key : keySet) {
            docList.add(new Document(key, filter.get(key)));
        }
        Collation.Builder numericOrdering = Collation.builder().locale("zh").numericOrdering(true);
        Collation collation = numericOrdering.build();
        FindIterable<Document> findIterable = coll.find(new Document("$and", docList)).skip(skip)
                .limit(size).collation(collation).sort(new Document(orderBy, order));
        long totalCount = coll.count(new Document("$and", docList));
        if (childFilter.size() != 0) {
            // 子级查找
            List<Document> childList = new ArrayList<>();
            Set<String> childKeySet = childFilter.keySet();
            for (String key : childKeySet) {
                childList.add(new Document(key, childFilter.get(key)));
            }
            findIterable = coll.find(new Document("$and", childList)).skip(skip)
                    .limit(size).collation(collation).sort(new Document(orderBy, order));
            totalCount = coll.count(new Document("$and", childList));
        }
        MongoCursor cursor = findIterable.iterator();
        while (cursor.hasNext()) {
            Map m = (Map) cursor.next();
            m.remove("_id");
            m.remove("_class");
            list.add(m);
        }
        Map<String, Object> totalRecords = new HashMap();
        totalRecords.put("paperList", list);
        totalRecords.put("totalRecords", totalCount);
        return totalRecords;
    }

    /**
     * 指定key/value分页取出数据.
     */
    public <T> List<T> findByPage(int pageNum, int size, String collectionName, Class<T> clazz) {
        if (pageNum < 1) {
            pageNum = 1;
        }
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        query.skip((pageNum - 1) * size);
        query.limit(size);
        return mongoTemplate.find(query, clazz, collectionName);
    }

    /**
     * 指定key/value取出所有数据,使用in条件,传入Object[]类型数组.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public List<Map> findAllWithIn(String[] prokeys, Object[] provalues,
                                   String collectionName, String orderBy, Integer order) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (int i = 0; i < prokeys.length; i++) {
            if (provalues[i] instanceof Object[]) {
                query.addCriteria(Criteria.where(prokeys[i]).in((Object[]) provalues[i]));
            } else {
                query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
            }
        }
        if (orderBy != null && order != null) {
            Direction direction;
            if (order < 0) {
                direction = Direction.DESC;
            } else {
                direction = Direction.ASC;
            }
            query.with(new Sort(new Order(direction, orderBy)));
        }
        return mongoTemplate.find(query, Map.class, collectionName);
    }

    /**
     * 指定key/value取出所有数据,使用in条件,传入Object[]类型数组.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public List findAllWithIn(String[] prokeys, Object[] provalues,
                              String collectionName, Class entityClass,
                              String orderBy, Integer order) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (int i = 0; i < prokeys.length; i++) {
            if (provalues[i] instanceof Object[]) {
                query.addCriteria(Criteria.where(prokeys[i]).in((Object[]) provalues[i]));
            } else {
                query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
            }
        }
        if (orderBy != null && order != null) {
            Direction direction;
            if (order < 0) {
                direction = Direction.DESC;
            } else {
                direction = Direction.ASC;
            }
            query.with(new Sort(new Order(direction, orderBy)));
        }
        return mongoTemplate.find(query, entityClass, collectionName);
    }

    /**
     * 指定key/value取出所有数据.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public List<Map<String, Object>> findAll(String[] prokeys, Object[] provalues,
                                             String collectionName, String orderBy, Integer order) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        List<Map<String, Object>> list = new ArrayList<>();
        Document doc = new Document();
        for (int i = 0; i < prokeys.length; i++) {
            doc.append(prokeys[i], provalues[i]);
        }
        FindIterable iter = coll.find(doc).sort(new Document(orderBy, order));
        MongoCursor cursor = iter.iterator();
        while (cursor.hasNext()) {
            Map m = (Map) cursor.next();
            m.remove("_id");
            list.add(m);
        }
        return list;
    }

    /**
     * 指定key/value取出所有数据.
     *
     * @param filter         筛选条件
     * @param collectionName 集合名
     * @param orderBy        排序字段
     * @param order          1:升序 -1:降序
     */
    public List<Map<String, Object>> findAll(Map<String, Object> filter,
                                             Map<String, Object> childFilter,
                                             String collectionName, String orderBy, Integer order) {
        MongoCollection coll = MongoTools.getCollection(collectionName);
        List<Map<String, Object>> list = new ArrayList<>();
        List<Document> docList = new ArrayList<>();
        Set<String> keySet = filter.keySet();
        for (String key : keySet) {
            docList.add(new Document(key, filter.get(key)));
        }
        Collation.Builder numericOrdering = Collation.builder().locale("zh").numericOrdering(true);
        Collation collation = numericOrdering.build();
        FindIterable<Document> findIterable = coll.find(new Document("$and", docList))
                .collation(collation).sort(new Document(orderBy, order));
        if (childFilter.size() != 0) {
            // 子级查找
            List<Document> childList = new ArrayList<>();
            Set<String> childKeySet = childFilter.keySet();
            for (String key : childKeySet) {
                childList.add(new Document(key, childFilter.get(key)));
            }
            findIterable = coll.find(new Document("$and", childList)).collation(collation)
                    .sort(new Document(orderBy, order));
        }
        MongoCursor cursor = findIterable.iterator();
        while (cursor.hasNext()) {
            Map m = (Map) cursor.next();
            m.remove("_id");
            m.remove("_class");
            list.add(m);
        }
        return list;
    }

    /**
     * 指定key/value取出所有数据(指定字段且多排序).
     *
     * @param prokeys        key
     * @param provalues      value
     * @param includeFields  指定字段
     * @param collectionName 集合名
     * @param orderBys       排序字段
     * @param orders         1:升序 -1:降序
     */
    public List<Map<String, Object>> findAllByArrOrderAndProjection(
            String[] prokeys, Object[] provalues, String[] includeFields,
            String collectionName, String[] orderBys,
            Integer[] orders) {
        List<Map<String, Object>> list = new ArrayList<>();
        Document doc = new Document();
        Document filter = new Document();
        Document order = new Document();
        for (int i = 0; i < prokeys.length; i++) {
            doc.append(prokeys[i], provalues[i]);
        }
        for (int i = 0; i < orderBys.length; i++) {
            order.append(orderBys[i], orders[i]);
        }
        for (int i = 0; i < includeFields.length; i++) {
            filter.append(includeFields[i], true);
        }
        MongoCollection coll = MongoTools.getCollection(collectionName);
        FindIterable iter = coll.find(doc).projection(filter).sort(order);
        MongoCursor cursor = iter.iterator();
        while (cursor.hasNext()) {
            Map m = (Map) cursor.next();
            m.remove("_id");
            list.add(m);
        }
        return list;
    }

    /**
     * 根据key/value获取bean.
     *
     * @param prokeys        key
     * @param provalues      value
     * @param collectionName 集合名
     * @param countField     累计字段
     * @param groupBy        分组字段
     */
    public List<Map<String, Object>> findAllByGroup(
            String[] prokeys, Object[] provalues, String collectionName,
            String countField, String groupBy) {
        Criteria criteria = new Criteria();
        Criteria[] criterias = new Criteria[prokeys.length];
        for (int i = 0; i < prokeys.length; i++) {
            criterias[i] = Criteria.where(prokeys[i].toString()).is(provalues[i]);
        }
        if (prokeys.length > 0) {
            criteria.andOperator(criterias);
        }
        GroupBy gb = new GroupBy(groupBy);
        if (countField != null && countField != "") {
            gb = gb.initialDocument("{count: 0}")
                    .reduceFunction("function (doc,pre){pre.count += doc." + countField + ";}");
        }
        GroupByResults groupByResults = mongoTemplate.group(criteria, collectionName, gb, Map.class);
        return (List<Map<String, Object>>) groupByResults.getRawResults().get("retval");
    }

    /**
     * 添加/更新符合条件的数据.
     *
     * @param querys         查询条件集合
     * @param updates        更新条件集合
     * @param collectionName 集合名
     */
    public void upsert(Map<String, Object> querys, Map<String, Object> updates,
                       String collectionName) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        for (Map.Entry e : querys.entrySet()) {
            query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
        }
        Update update = new Update();
        for (Map.Entry e : updates.entrySet()) {
            update.set(e.getKey().toString(), e.getValue());
        }
        // 新版本entityClass必传
        mongoTemplate.upsert(query, update, Map.class, collectionName);
    }

    /**
     * 更新指定key的数据.
     *
     * @param prokeys        待更新字段名
     * @param provalues      待更新字段值
     * @param collectionName 集合名
     */
    public void updateOne(String key, Integer id, String[] prokeys, Object[] provalues,
                          String collectionName) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        Criteria criteria = new Criteria(key);
        criteria.is(id);
        Update update = new Update();
        for (int i = 0; i < prokeys.length; i++) {
            update.set(prokeys[i].toString(), provalues[i]);
        }
        query.addCriteria(criteria);
        mongoTemplate.updateFirst(query, update, Map.class, collectionName);
    }

    /**
     * 插入map.
     *
     * @param collectionName 集合名
     */
    public void insert(Map<String, Object> map, String collectionName) throws IllegalAccessException {
        mongoTemplate.insert(map, collectionName);
    }

    /**
     * 插入bean.
     *
     * @param collectionName 集合名
     */
    public void insertMongo(Object object, String collectionName) {
        mongoTemplate.insert(object, collectionName);
    }

    /**
     * 删除指定key的数据.
     *
     * @param id             key值
     * @param collectionName 集合名
     */
    public void removeOne(String key, Object id, String collectionName, Class clazz) {
        org.springframework.data.mongodb.core.query.Query query =
                new org.springframework.data.mongodb.core.query.Query();
        Criteria criteria = new Criteria(key);
        criteria.is(id);
        query.addCriteria(criteria);
        mongoTemplate.remove(query, clazz, collectionName);
    }

    /**
     * 重命名集合.
     */
    public void renameCollection(String oldCollection, String newCollection) {
        if (!mongoTemplate.collectionExists(oldCollection)) {
            return;
        }
        if (mongoTemplate.collectionExists(newCollection)) {
            mongoTemplate.dropCollection(newCollection);
        }
        MongoCollection mongoCollection = mongoTemplate.getCollection(oldCollection);
        mongoCollection
                .renameCollection(new MongoNamespace(mongoTemplate.getDb().getName(), newCollection));
    }

    /**
     * 删除collection.
     */
    public void removeCollection(String collection) {
        if (!mongoTemplate.collectionExists(collection)) {
            return;
        } else {
            mongoTemplate.dropCollection(collection);
        }
    }
}

yml 文件配置:

spring:
  data:
    mongodb:
      host: 127.0.0.1
      port: 27017
      database: testdb
      username: test
      password: password

 

posted @ 2012-04-18 11:08  Charles Zhang  阅读(1035)  评论(0编辑  收藏  举报