[컴][자바][웹] Spring 에서 Spring Data MongoDB 사용하는 법

스프링에서 몽고db 사용

Spring 에서 MongoDB 의 data 를 handling 하기 위해 제공하는 library(framework 라 해야 하나.)가 있다.

여하튼 code 로 만드는 것보단 xml setting 이 가능하면 좋을 듯 싶어 사용해 보고 있다. 아래에서 사용법을 확인 해 볼 수 있다.


Spring Data MongoDB 사용법


MongoTemplate
core class 중 하나
  • MongoDB server 에 접속
  • 관련된 resource 들을 관리하고
  • 기능들과 관련된 간편한 API 를 제공한다.

MongoTemplate 의 4가지의 constructor 가 있다.

  • MongoTemplate (Mongo mongo, String databaseName) - takes the com.mongodb.Mongo object and the default database name to operate against.
  • MongoTemplate (Mongo mongo, String databaseName, UserCredentials userCredentials) - adds the username and password for authenticating with the database.
  • MongoTemplate (MongoDbFactory mongoDbFactory) - takes a MongoDbFactory object that encapsulated the com.mongodb.Mongo object, database name, and username and password.
  • MongoTemplate (MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) - adds a MongoConverter to use for mapping.


MongoDbFactory 는 Mongo class 의 정보에 아이디, 비밀번호등의 추가적인 정보들을 가진 class 이다. 그래서 Mongo class 와 함께 database 이름을 같이 MongoTemplate 으로 넘기는 대신에 database 이름을 가진 MongoDbFactory 를 만들고 그것을 대신 넘길 수 있다.





Spring Data MongoDB 의 예제


aggregation 사용예제

  1. spring-data-mongodb/AggregationTests.java at master · spring-projects/spring-data-mongodb · GitHub


mongo db xml 설정 관련 참고






spring data mongoDB 설정

아래와 같이 .xml 설정으로 MongoTemplate bean 을 만들고, @Autowired 를 사용해서 MongoTemplate 를 이용할 수 있다.



<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:beans="http://www.springframework.org/schema/beans"
    
    xmlns:mongo="http://www.springframework.org/schema/data/mongo" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd
     
             http://www.springframework.org/schema/data/mongo
             http://www.springframework.org/schema/data/mongo/spring-mongo.xsd"

    
        >
    
    

    <mongo:mongo id="mongo" host="${mongo.ip}" port="${mongo.port}" >
<!--         <mongo:options
             connections-per-host="${mongo.connectionsPerHost}"
             threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
             connect-timeout="${mongo.connectTimeout}"
             max-wait-time="${mongo.maxWaitTime}"
             auto-connect-retry="${mongo.autoConnectRetry}"
             socket-keep-alive="${mongo.socketKeepAlive}"
             socket-timeout="${mongo.socketTimeout}"
             slave-ok="${mongo.slaveOk}"
             write-number="1"
             write-timeout="0"
             write-fsync="true"/> -->
    </mongo:mongo>

    <mongo:db-factory id="mongoDbFactory" mongo-ref="mongo"
                  dbname="${mongo.db}"
                  username="${mongo.username}"
                  password="${mongo.password}"/>



    <!-- MongoTemplate for connecting and quering the documents in the database -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    </bean>
 
    <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
     



</beans>



// CdnReportService.java
public interface CdnReportService {
  ...
    
  AggregationOutput getDomainTraffic();
}  

// CdnReportServiceImpl.java
@Service
public class CdnReportServiceImpl implements CdnReportService{
  

    @Autowired
    private MongoTemplate mongoTemplate;
  
  
    public AggregationOutput getDomainTraffic(){

      final String collectionName = "traffic";
      
      List<DBObject> ops = new ArrayList<DBObject>();
      ops.add(getMatchOperation());
      ops.add(getGroupOperation());
      ops.add(getGroupOperation2());
      ops.add(new BasicDBObject("$sort",
                                      new BasicDBObject(
                                            "_id.datetime",
                                            1)));
      
      
      return mongoTemplate.getCollection(collectionName).aggregate(ops);

    }
}




object-document mapper 사용하기

private CdnReportService reportService;
...
AggregationResults<MongoModelCdnReportDomainTraffic> outputList
   = reportService.getDomainTrafficHour(period);


// MongoModelCdnReportDomainTraffic.java
public class MongoModelCdnReportDomainTraffic {

 private String id; // datetime
 private List<Long> domainSeqs;
 private List<Long> cdnSvcIds;
 private List<Long> traffics;
 ...




// CdnReportServiceImple.java
@Service
public class CdnReportServiceImpl implements CdnReportService{
 
 @Autowired
 private CdnReportMapper cdnReportMapper;

 @Autowired
 private MongoTemplate mongoTemplate;

 ...
 public AggregationResults<MongoModelCdnReportDomainTraffic> getDomainTrafficHour(Period p){

 /**
 * 
 {$match:{ 
     "domain_seq" : {$exists:true},
     datetime : { "$gte" : "2014070100" , "$lte" : "2014070123"}
     }
   },
  { $group:{ 
    _id : {domain_seq:"$domain_seq", datetime : "$datetime"},
    cdn_svc_id : {$first : "$cdn_svc_id"},
    traffic : {$sum : "$traffic"}
    }
  },
  { $group:{ 
    _id : "$_id.datetime",
    domain_seq : {$push : "$_id.domain_seq"},
    cdn_svc_id : {$push : "$cdn_svc_id"},
    traffic : {$push : "$traffic"}
    }
  },
  { $sort:{ 
    "_id":1
    }
  }
 */
 /**
  * @see Aggregation.toDbObject to see the query generated
  */
 Aggregation agg = Aggregation.newAggregation(
   Aggregation.match(Criteria.where("domain_seq").exists(true)
   .and("datetime").gte(p.getFromYyyyMMddHH()).lte(p.getToYyyyMMddHH())),

  Aggregation.group("domain_seq", "datetime")
      .first("cdn_svc_id").as("cdn_svc_id")
      .sum("traffic").as("traffic"),
  
  Aggregation.group("datetime")
      .push("domain_seq").as("domainSeqs")
      .push("cdn_svc_id").as("cdnSvcIds")
      .push("traffic").as("traffics"),
  
  Aggregation.sort(Sort.Direction.ASC, "_id") // sorted by the datetime
  );

 

 return mongoTemplate.aggregate(agg,
    "real_traffic_stat_hh", 
    MongoModelCdnReportDomainTraffic.class);


}




Tips

AggregationResults 의 DataType 에서 id 가 여러개인 경우


아래처럼 result set 의 entity 가 아래와 같은 경우 Model Class 를 어떻게 만들어야 하나? 처음에 id 를 Map 이나 Set 으로 해봤는데, 안됐다. 그냥 손쉽게 이름에 맞춰서 field 를 만들어 주면 알아서 결과를 넣어준다.

{ "_id" : { "time" : "20141101" , "code" : 7} , "count" : 95}

public class MongoModelType {

 private String time;
 private int code;
 private long count;
        ...
}


aggregation 에서 아래처럼 group operation 을 만들때

{ "$group" : { "_id" : { "time" : "$time" , "new_code" : "$code"}

Aggregation.group(Fields.from(Fields.field("time"), Fields.field("new_code", "code")))


DBObject to AggregationOperation 

ref. 2 에서 아주 좋은 방법을 제시해준다. ref. 2 의 DBObjectAggregationOperation class 를 이용해서 아래처럼 손쉽게 query 를 작성할 수 있으면, framework 에서 지원하지 않는 query 도 사용할 수 있다.

new DBObjectAggregationOperation((DBObject) JSON.parse(
    String.format("{\"$match\":" +
                    "{ \"id\" : %d, \"dseq\" : %d, \"pid\" : %d," +
                    " date : { \"$gte\" : \"%s\" , \"$lte\" : \"%s\"}}" +
                    "}",
            param.getId(),
            param.getDSeq(),
            param.getPid(),
            param.getStartDateString(), param.getEndDateString())));



References

댓글 없음:

댓글 쓰기