MongoDB를 사용하다보면, RDB에 익숙한 우리는 Join 이 없다는 사실에 충격을 먹게된다.
괜히 몽고를...
다만, 이와 비슷한 구현으로 lookup를 활용해 Join과 동일한 효과를 낼 수 있다. 야호! 그러면 한번 해볼까?
예시 코드
mongo> db.orders.aggregate(
[
{
$lookup : {
from : "products"
, localField : "product_id"
, foreignField : "product_id"
, as : "order_product"
}
}
]
);
무슨 소리인지 알기 어렵다. 그러나 $lookup에 해당하는 부분이 보인다.
여기서
from 은 lookup를 할 대상인 collection을,
localField 는 from뒤의 collection의 참조할 Field,
foreignField는 원래 사용하고 있던 collection의 Field,
as는 alias로 사용되고,
뒤의 project와 같은 함수에서 "order_product.product_id"와 같은 방식으로 값을 불러올 수 있다.
Aggregate
일반적인 query를 직접 넣었던 것과는 다르게, 해당 함수는 filter, sort 등 다양한 연산을 할 수 있도록 돕는다.
해당 부분의 자세한 설명은 다른 포스팅에서 진행하겠다! 너무 궁굼하다면 밑을 한번 살펴보자!
간략하게 설명하자면, RDB에서 사용되는 함수를 몽고 함수랑 연관되는 함수를 붙여놓은 것이다. 실제로 더 많은 함수가 존재한다.
SpringBoot 에서의 구현
MongoTemplate를 사용할 수 있는 상태라면 밑의 함수들을 모두 나타낼 수 있다.
물론 @Query 어노테이션을 활용하여 일일히 쓸 수 있겠지만, 객체지향성 및 자바의 깔꼼한 코드 스타일이 좋다면 아래와 같이 코드를 작성할 수 있다.
@Override
public CafeJoinOperatingTimeDto findByIdwithOperatingTime(String cafeId) {
Criteria criteria = Criteria.where("cafeId").is(cafeId);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.lookup("cafeOperatingTime", "cafeId", "cafeId", "cafeOperatingTime"),
Aggregation.project("cafeId", "cafeName", "cafeImg")
.and("cafeOperatingTime.openTime").arrayElementAt(0).as("openTime")
.and("cafeOperatingTime.closeTime").arrayElementAt(0).as("closeTime")
);
CafeJoinOperatingTimeDto cafeJoinOperatingTimeDto = mongoTemplate.aggregate(aggregation, Cafe.class, CafeJoinOperatingTimeDto.class).getUniqueMappedResult();
return cafeJoinOperatingTimeDto;
우선, cafeId가 변수로 준 cafeId를 같게 한다는 match,
lookup 함수를 활용하여 (from, localfield, foreignfield, as)를 작성해주고
project 을 통해서 나타내고자 하는 attribute를 설정해주었다.
기억해야 할 부분
삽질했던 부분은 openTime과 closeTime을 가져왔을 때에 dataType이 맞지 않아서 꽤나 길게 고민했다. 이때 lookup한 컬렉션의 칼럼을 가져와서 사용할 경우 리스트 형태로 나타나게 된다. 그래서 굳이굳이 arrayElementAt(0)을 활용해서 리스트 값에서 꺼내주어 원래의 데이터 타입으로 받을 수 있었다. (원래 데이터 타입이 List<TableOption> 으로 TableOption은 직접 만들었던 enum 타입의 변수이다.)
'MongoDB' 카테고리의 다른 글
MongoDB JPA 처럼 객체로 foreignkey를 사용할 수 없을까? (0) | 2023.07.03 |
---|---|
MongoDB 의 MongoTemplate 활용하기 - JPA 위에 덧씌우기 (0) | 2023.07.01 |