NoSQL과 관련하여 가장 자주 받는 질문 중 하나는 여러 문서의 데이터를 단일 쿼리 결과로 조인하는 문제입니다. 이 질문은 RDBMS 개발자들로부터 더 자주 제기되지만, 저는 NoSQL 개발자들로부터도 이 질문을 받습니다.

데이터 조인은 데이터베이스마다 다르게 수행되며, 그 중 일부는 데이터베이스 계층이 아닌 애플리케이션 계층을 통해 수행해야 합니다. 데이터베이스 기술 간의 몇 가지 데이터 조인 옵션을 살펴보겠습니다.

이 블로그에서는 MongoDB $lookup 연산자를 사용하여 NoSQL 문서를 조인하는 프로세스를 다음과 비교해보겠습니다. 카우치베이스의 보다 직관적인 N1QL 쿼리 언어입니다.

샘플 데이터

이 예제에서는 두 개의 샘플 문서를 기반으로 MongoDB와 Couchbase를 모두 사용하겠습니다. 일반적인 주문 및 재고 예제로 작업한다고 가정해 보겠습니다. 인벤토리의 경우 문서는 다음과 같이 보일 수 있습니다:

위 문서는 평면적이지만 특정 제품을 제대로 설명할 수 있습니다. 여기에는 조인 프로세스 중에 관련되는 고유 ID가 있습니다. 주문의 경우 다음과 같은 문서가 있을 수 있습니다:

여기서는 MongoDB와 Couchbase를 모두 사용하여 이 두 문서를 단일 쿼리로 조인하는 것이 목표입니다. 그러나 쿼리 언어와는 별개로, 이러한 문서는 애플리케이션 계층을 통해 언제든지 여러 쿼리를 통해 조인할 수 있습니다. 하지만 이것이 우리가 원하는 결과는 아닙니다.

MongoDB와 $lookup 연산자로 문서 조인하기

최신 버전의 MongoDB에서 조인 쿼리에는 $조회 연산자를 사용하여 집계 쿼리의 일부로 사용할 수 있습니다. 몽고DB 문서로 설정하면 이 연산자는 다음과 같이 수행됩니다:

동일한 데이터베이스에서 샤딩되지 않은 컬렉션에 왼쪽 외부 조인을 수행하여 "조인된" 컬렉션의 문서를 필터링하여 처리합니다. $lookup 단계에서는 입력 문서의 필드와 "조인된" 컬렉션의 문서 필드 간에 동일성 일치를 수행합니다.

사용하려면 $조회 연산자를 사용하면 다음과 같은 결과가 나타납니다:

이제 이것은 훌륭하지만 배열에서 발견되는 관계에서는 작동하지 않습니다. 즉, 배열의 $조회 작업에 참여할 수 없습니다. product_id 에서 찾을 수 있습니다. 제품 배열을 다른 문서에 추가할 수 없습니다. 대신 배열을 먼저 '언와인드' 또는 '언네스트'해야 하므로 쿼리가 더욱 복잡해집니다:

그리고 $unwind 연산자는 배열을 평평하게 한 다음 생성된 이제 평평해진 개체에 대해 조인을 수행합니다. 이러한 쿼리의 결과는 다음과 같습니다:

배열에 참조가 두 개 이상 있었다면 더 많은 결과가 반환되었을 것입니다. 그러나 반환되는 결과는 그다지 매력적이지 않습니다. 여전히 이전 제품 객체에서 이제 제품 개체 배열을 추가합니다. 데이터 스트림에 대한 추가 조작이 필요합니다.

그리고 제품 개체 배열을 "언와인드"한 다음 원하는 방식으로 재구성해야 합니다. 이를 위해서는 다음을 수행하면 됩니다:

참고 집계 쿼리는 이제 더 복잡해지고 있습니다. 조인을 수행한 후 결과를 "언와인드"한 다음 다음을 사용하여 결과를 재구성합니다. $프로젝트 연산자입니다.

이 시점에서 결과를 그룹화하는 등 결과에 대한 추가 조작을 수행할 수 있습니다. 제품 객체가 다시 단일 배열이 됩니다. 데이터 집합을 조작할 때마다 더 많은 집계 코드가 필요하므로 쉽게 지저분하고 복잡해지며 읽기 어려워질 수 있습니다.

이 부분에서 Couchbase N1QL을 사용하면 훨씬 더 즐겁게 작업할 수 있습니다.

카우치베이스와 N1QL을 사용하여 NoSQL 문서 조인하기

MongoDB에 사용한 것과 동일한 문서 예제를 사용하겠습니다. 이번에는 작업을 완료하기 위해 N1QL로 SQL 쿼리를 작성해 보겠습니다.

가장 먼저 떠오르는 것은 아마도 JOIN 를 입력합니다. 쿼리는 다음과 같이 보일 수 있습니다:

위의 예에서는 두 문서가 모두 동일한 Couchbase 버킷에 존재합니다. A JOIN 문서 ID에 대한 product_id 값에 있는 제품 배열을 사용합니다. 위의 쿼리는 다음과 같은 결과를 반환합니다:

몽고DB와 마찬가지로, 모든 항목에 대한 결과가 있습니다. 제품 배열을 찾아야 합니다. 공정하게 말하자면, N1QL 버전이 작성하기는 더 쉬웠지만, 이 시점에서 몽고DB 쿼리 언어보다 반드시 더 어려운 것은 아니었습니다. 데이터를 더 많이 조작할수록 Couchbase는 그에 비해 훨씬 더 쉬워집니다.

예를 들어 결과를 정리하고 싶다고 가정해 보겠습니다:

위에서 수행하는 작업에는 몇 가지 큰 차이점이 있지만, 수행 방법에는 약간의 차이가 있습니다. 배열에 직접 조인하는 대신, 먼저 MongoDB에서 본 것과 같이 배열을 평평하게 하거나 "중첩 해제"합니다. $unwind 연산자를 사용합니다. 이제 각각의 평평한 결과에서 조인이 수행됩니다. 마지막으로 수량 를 새 개체에 추가합니다.

위 쿼리에 대한 결과는 다음과 같습니다:

원본 제품 배열에 둘 이상의 제품 참조가 포함되어 있습니다. 배열에 따라 여러 개의 객체를 반환하는 대신 JOIN 기준에 따라 원래 배열을 다시 패킹하는 것이 합리적일 수 있습니다.

위의 쿼리에서는 다음과 같은 항목만 추가했습니다. ARRAY_AGG그룹 기준로 표시되지만 결과적으로 각 조인된 문서는 제품 배열을 사용합니다.

실제 JOIN 연산자를 사용하시나요? 대신 SQL 하위 쿼리를 사용해 보세요.

결론

NoSQL에서 데이터 조인은 숙련된 RDBMS 베테랑 개발자들에게 매우 인기 있는 관심사입니다. MongoDB는 매우 인기 있는 NoSQL 기술이기 때문에 Couchbase가 문서 조인을 처리하는 방식과 비교하는 데 사용하면 좋겠다고 생각했습니다. 가벼운 작업용, $조회 연산자는 견딜 수 있지만, MongoDB의 조인 쿼리가 더 복잡해지면 한 걸음 물러서야 할 수도 있습니다. N1QL을 사용하면 조인 연산이 포함된 복잡한 쿼리를 매우 쉽게 작성할 수 있으며 쿼리가 얼마나 복잡한지에 관계없이 쉽게 유지됩니다.

N1QL 및 Couchbase에 대한 자세한 내용은 다음을 참조하세요. 카우치베이스 개발자 포털.

작성자

게시자 Nic Raboy, 개발자 옹호자, Couchbase

닉 라보이는 최신 웹 및 모바일 개발 기술을 옹호하는 사람입니다. 그는 Java, JavaScript, Golang 및 Angular, NativeScript, Apache Cordova와 같은 다양한 프레임워크에 대한 경험이 있습니다. Nic은 웹 및 모바일 개발을 보다 쉽게 이해할 수 있도록 자신의 개발 경험에 대해 글을 쓰고 있습니다.

댓글 남기기