使用morphia实现对mongodb的聚合查询

时间:2021-04-17 08:43:11

  morphia是谷歌的一个针对mongodb的数据化持久框架;
  关于mongodb的介绍不在这里展示,直接进入主题:采用morphia实现对mongodb的聚合查询

  这里获取所有学生的分数总和

 

  spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
   default-autowire="byName">
   <bean id="mongoDBManager" class="com.snake.bsys.common.db.MongoDBManager" scope="singleton" >
      <property name="serverIpAddr">
         <value>127.0.0.1</value>
      </property>

      <property name="serverPort">
         <value>27017</value>
      </property>

      <property name="userName">
         <value>用户名</value>
      </property>
      <property name="userPsw">
         <value>密码</value>
      </property>
      <property name="connSource">
         <value>库名</value>
      </property>
   </bean>

   <bean id="simpleMongoDBDao" class="com.snake.bsys.common.db.SimpleMongoDBDao" scope="singleton" >
      <property name="dbName">
         <value>库名</value>
      </property>
   </bean>
</beans>
public class SimpleMongoDBDao<T> {

    String dbName;

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    public Datastore getDB() {
        Datastore datastore = MongoDBManager.getDB(dbName);
        return datastore;
    }


    public Pagination queryForPage(Pagination pagination, Query query) {
        try {

            //每页显示条数
            int pageSize = pagination.getPageSize();
            //第几页
            int pageCount = pagination.getPageNo();
            //总记录数
            int recordCount = pagination.getTotalCount();

            //获取总记录数
            recordCount = (int) query.count();
            //总记录数
            pagination.setTotalCount(recordCount);

            //第一条数据位置
            int firstResult = pagination.getFirstResult();
            firstResult = firstResult < 0 ? 0 : firstResult;

            FindOptions findOptions = new FindOptions();
            //起始位置
            findOptions.skip(firstResult);
            //查询条数
            findOptions.limit(pageSize);

            //当前页码
            pagination.setPageNo(pagination.getPageNo());
            //总页数
            pagination.setPageSize(PageHelper.getPageCount(recordCount, pagination.getPageSize()));
            List<T> list = query.asList(findOptions);
            pagination.setList(list);
            return pagination;
        } catch (Exception e) {
            e.printStackTrace();
            Log.logger.error(e.getMessage(), e);
        }
        return null;
    }


    public T getOne(Class classT, String colName, Object equalObj) {
        try {
            Datastore datastore = this.getDB();

            Query<T> query = datastore.createQuery(classT);
            query = query.field(colName).equal(equalObj);
            List<T> list = query.asList();
            if (list != null && list.size() > 0)
                return list.get(0);

        } catch (Exception ex) {
            ex.printStackTrace();
            Log.logger.error(ex.getMessage(), ex);
        }

        return null;
    }
}


public class MongoDBManager {

    String serverIpAddr="";
    int serverPort=0;
    String userName="";
    String userPsw="";
    String connSource="";

    public String getServerIpAddr() {
        return serverIpAddr;
    }

    public void setServerIpAddr(String serverIpAddr) {
        this.serverIpAddr = serverIpAddr;
    }

    public int getServerPort() {
        return serverPort;
    }

    public void setServerPort(int serverPort) {
        this.serverPort = serverPort;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPsw() {
        return userPsw;
    }

    public void setUserPsw(String userPsw) {
        this.userPsw = userPsw;
    }

    public String getConnSource() {
        return connSource;
    }

    public void setConnSource(String connSource) {
        this.connSource = connSource;
    }

    MongoClient mongoClient;
    Morphia morphia;

    private static MongoDBManager runInstance;

    /**
     * 初始化连接池
     */
    public void initConn() {
        // 其他参数根据实际情况进行添加
        try {

            morphia = new Morphia();
            // 告诉Morphia在哪里找到你的类
            // 可以为不同的包或者类进行多次的调用
            morphia.mapPackage("");

            ServerAddress serverAddress = new ServerAddress(serverIpAddr,serverPort);
            List<ServerAddress> addrs = new ArrayList<ServerAddress>();
            addrs.add(serverAddress);

            //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
            MongoCredential credential = MongoCredential.createScramSha1Credential(userName, connSource, userPsw.toCharArray());
            List<MongoCredential> credentials = new ArrayList<MongoCredential>();
            credentials.add(credential);
            mongoClient = new MongoClient(addrs,credentials);

            runInstance=this;

            Log.logger.info("mongoDB 初始化完成 init OK....at:"+ DateUtil.getStandardDate(new Date()));
        } catch (Exception e) {
            e.printStackTrace();
            Log.logger.error("mongoDB 失败,"+e.getMessage(),e);
        }

    }

    public static Datastore getDB(String dbName){
        Datastore datastore=null;
        if(runInstance.mongoClient!=null&&runInstance.morphia!=null){
            datastore = runInstance.morphia.createDatastore(runInstance.mongoClient, dbName);
            datastore.ensureIndexes();
        }else{
            Log.logger.warn("mongoDB 未初始化!");
        }
        return datastore;
    }
}
  实体类:

package com.luo.model;

import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;


@Entity(value = "user_score", noClassnameStored = true)
public class UserDoc {
    @Id
    private Object mgId;
    private String name;
    private Integer score;


    public Object getMgId() {
        return mgId;
    }

    public void setMgId(Object mgId) {
        this.mgId = mgId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }
}

  //需要封装结果集:
package com.luo.model;


import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;

@Entity
public class ScoreGroupDOC {
    @Id
    private Object mgId;
    private Integer totalScore;

    public Object getMgId() {
        return mgId;
    }

    public void setMgId(Object mgId) {
        this.mgId = mgId;
    }

    public Integer getTotalScore() {
        return totalScore;
    }

    public void setTotalScore(Integer totalScore) {
        this.totalScore = totalScore;
    }
}
 
 

 





package com.luo.model;

import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.aggregation.AggregationPipeline;
import org.mongodb.morphia.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Iterator;

import static org.mongodb.morphia.aggregation.Group.grouping;
import static org.mongodb.morphia.aggregation.Group.id;
import static org.mongodb.morphia.aggregation.Group.sum;


@Service
public class UserService {
    @Resource
    SimpleMongoDBDao<UserDoc> simpleMongoDBDao;
    public ScoreGroupDOC getTotalScore(){
        Datastore datastore = simpleMongoDBDao.getDB();
        Query<UserDoc> query = datastore.createQuery(UserDoc.class);//查询对象
        /*获取分数合计*/
        AggregationPipeline pipeline = datastore.createAggregation(UserDoc.class)
                                                           //封装到结果集的字段      获取聚合的字段       
                .match(query).group(id(grouping("mgId")),grouping("totalScore", sum("score")));
        Iterator<ScoreGroupDOC> iterator = pipeline.aggregate(ScoreGroupDOC.class);
        ScoreGroupDOC groupDOC = new ScoreGroupDOC();
        while (iterator.hasNext()) {
            groupDOC = iterator.next();
        }
        return groupDOC;
    }
}

 

   一个刚入行不久的新手程序员也是刚刚接触mongoDB不到一周的时间,第一次写。做个记录,morphia这个框架在网上的资料实在太少了。当时为了求账单的金额合计查了一整天的资料。东拼西凑最终还是把结果做出来了。不过说实在的速度虽然比mySql要好一些。50多万条数据在我自己的笔记本上还是需要2秒多的时间。希望有高手指点一下 提升一下我的聚合查询速度;

  不甚感激;