Spring 에서 MongoDB 의 data 를 handling 하기 위해 제공하는 library(framework 라 해야 하나.)가 있다.
여하튼 code 로 만드는 것보단 xml setting 이 가능하면 좋을 듯 싶어 사용해 보고 있다. 아래에서 사용법을 확인 해 볼 수 있다.
Spring Data MongoDB 사용법
- Spring Data MongoDB - Reference Documentation
- 5. MongoDB repositories
- Overview of Spring Data MongoDB - Zenika
MongoTemplate
core class 중 하나
- MongoDB server 에 접속
- 관련된 resource 들을 관리하고
- 기능들과 관련된 간편한 API 를 제공한다.
MongoTemplate 의 4가지의 constructor 가 있다.
MongoDbFactory 는 Mongo class 의 정보에 아이디, 비밀번호등의 추가적인 정보들을 가진 class 이다. 그래서 Mongo class 와 함께 database 이름을 같이 MongoTemplate 으로 넘기는 대신에 database 이름을 가진 MongoDbFactory 를 만들고 그것을 대신 넘길 수 있다.
- 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 사용예제
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())));
댓글 없음:
댓글 쓰기