목차
- 소개
$UnionWith
의 지원 버전 확인- 네이티브 쿼리를 이용한 Union 연산
- 네이티브 쿼리 실행 방법
MongoCollection.aggregate
를 사용한 네이티브 쿼리 실행
- 코드 예시
MongoClient
설정MongoCollection
가져오기- 매치 쿼리 생성
- 매치 쿼리를
List<Document>
로 변환 $unionWith
로 쿼리 감싸기- 집계 연산 쿼리 추가
- 최종 쿼리 실행
1. 소개
MongoDB 4.4부터 SQL의 Union all
과 유사한 연산인 $UnionWith
를 지원합니다. 이 기능은 데이터베이스의 여러 컬렉션을 합치는 데 사용됩니다. 그러나 Spring Data MongoDB의 최신 버전인 spring-boot-start-data-mongodb:3.0.7은 spring-data-mongodb:4.0.6에 의존하고 있어 $UnionWith
와 관련된 기능을 사용할 수 없습니다.
따라서 네이티브 쿼리를 사용해야 합니다. 네이티브 쿼리는 MongoDatabase
인터페이스의 runCommand
메서드나 MongoCollection
의 aggregate
메서드를 사용하여 실행할 수 있습니다. 이를 통해 네이티브 쿼리 요청을 MongoDB 쿼리로 전달할 수 있습니다.
이 글에서는 MongoCollection
의 aggregate
메서드를 사용하여 네이티브 쿼리를 실행하는 방법을 알아보겠습니다.
2. $UnionWith
의 지원 버전 확인
$UnionWith
연산을 사용하기 전에 MongoDB 서버의 버전을 확인해야 합니다. $UnionWith
는 MongoDB 4.4 이상에서 지원되므로 해당 버전 이상이어야 합니다.
3. 네이티브 쿼리를 이용한 Union 연산
3.1. 네이티브 쿼리 실행 방법
네이티브 쿼리를 실행하는 방법은 MongoDatabase
의 runCommand
메서드나 MongoCollection
의 aggregate
메서드를 사용하는 것입니다. 이 중 MongoCollection.aggregate
를 사용하여 네이티브 쿼리를 실행해보겠습니다.
3.2. MongoCollection.aggregate
를 사용한 네이티브 쿼리 실행
MongoTemplate
에서 사용할 컬렉션을 지정하여 MongoCollection
인터페이스의 객체를 가져옵니다. 그런 다음, 네이티브 쿼리를 작성하고 List<Document>
형식으로 변환한 후, MongoCollection.aggregate(List<Document>)
메서드에 전달하여 쿼리를 실행합니다.
4. 코드 예시
아래는 Spring Data MongoDB에서 Union 연산을 수행하는 예시 코드입니다.
4.1. MongoClient
설정
먼저, MongoClient
를 생성하여 Spring Data MongoDB가 접근해야 할 데이터베이스를 확인합니다.
@Configuration
public class MongoConfig {
@Bean
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
}
4.2. MongoCollection
가져오기
MongoTemplate
에서 사용할 컬렉션을 지정하여 MongoCollection
인터페이스 객체를 가져옵니다.
mongoTemplate.getDb().getCollection(COLLECTION_NAME)
4.3. 매치 쿼리 생성
Union에 사용할 매치 쿼리를 생성하는 메서드를 작성합니다.
private List<String> generateMatchQuery(List<Target> targets) {
return targets.stream().map(target -> {
return "{\n"
+ " $match :{\n"
+ " where : \"" + target.getPageUrl() + "\",\n"
+ " \"what.uniqueSelector\" : \"" + target.getHtmlElement() + "\",\n"
+ " when : {\n"
+ " $gte : ISODate(\"" + target.getApplyStart() + "\"),\n"
+ " $lte : ISODate(\"" + target.getApplyEnd() + "\"),\n"
+ " },\n"
+ " \"what.eventType\" : \"" + target.getEventType() + "\"\n"
+ " }\n"
+ "}";
}).toList();
}
4.4. 매치 쿼리를 List<Document>
로 변환
생성된 여러 개의 매치 쿼리를 바탕으로 List<Document>
를 생성합니다. 첫 번째 쿼리는 그대로 추가하고, 나머지 쿼리는 $unionWith
로 감싸서 리스트에 추가합니다.
private List<Document> convert(List<Target> targets){
if(targets.size()==0){
throw new AnalyzeServiceException();
}
List<String> matchQuery= generateMatchQuery(targets);
List<Document> documents=new ArrayList<>();
documents.add(Document.parse(matchQuery.get(0)));
for(int idx=1;idx<targets.size();idx++){
documents.add(Document.parse(wrapUnionCommand(matchQuery.get(idx))));
}
return documents;
}
private String wrapUnionCommand(String query){
return "{ $unionWith : { coll : \""+COLLECTION_NAME+"\", pipeline: ["
+query+"]}}";
}
4.5. 집계 연산 쿼리 추가
중복 데이터를 제거하기 위해 집계 연산 쿼리를 추가하는 기능을 구현합니다. $unionWith
쿼리는 중복 데이터를 제거하지
않으므로 집계 연산을 추가하여 중복을 제거해야 합니다.
public String query(List<Document> convertResult, String aggregationQueryJson) {
List<Document> fullQuery= new ArrayList<>(convertResult.size()+2);
convertResult.forEach(document -> fullQuery.add(document));
fullQuery.add(Document.parse("{ $group: {_id: \"$$ROOT\"} }"));
fullQuery.add(Document.parse(aggregationQueryJson));
return convert(runAggregate(fullQuery));
}
이제 네이티브 String 쿼리를 List<Document>
형식으로 변환하는 과정을 마쳤습니다. 이를 MongoCollection.aggregate(List<Document>)
에 전달하여 Union 연산을 수행할 수 있습니다.
'Computer Science' 카테고리의 다른 글
Gitlab에 러너를 등록하기 (0) | 2023.07.13 |
---|---|
앤서블로 카프카 클러스터 구축하기 (0) | 2023.07.13 |
Github Action으로 Spring 프로젝트를 Kubernetes에 배포하기 (0) | 2023.03.06 |