Docs Menu
Docs Home
/
MongoDB Ops Manager
/ /

$lookup 작업 축소

이 페이지의 내용

  • 개요
  • 예시
  • 비정규화
  • 자세히 알아보기

$lookup 작업은 지정된 필드를 기반으로 동일한 데이터베이스에 있는 두 컬렉션의 데이터를 결합합니다. $lookup 작업은 데이터가 관계형 데이터베이스와 유사하게 구조화되어 있고 대규모 계층적 데이터 세트를 모델링해야 할 때 유용할 수 있습니다. 그러나 이러한 작업은 단일 컬렉션이 아닌 두 개의 컬렉션에서 로직을 읽고 수행해야 하기 때문에 속도가 느리고 리소스 집약적일 수 있습니다.

$lookup 작업을 자주 실행하는 경우 애플리케이션이 단일 컬렉션을 쿼리하여 필요한 모든 정보를 얻을 수 있도록 스키마를 재구성하는 것이 좋습니다. 내장된 문서 및 배열이 있는 MongoDB의 유연한 스키마 모델 을 활용하여 단일 문서 구조에서 데이터 간의 관계를 캡처할 수 있습니다. 이 비정규화된 모델 을 사용하면 MongoDB의 풍부한 문서를 활용하고 애플리케이션에서 단일 쿼리로 관련 데이터를 검색하고 조작할 수 있습니다.

다음 예제에서는 $lookup 작업을 줄이기 위해 설계된 두 가지 스키마 구조를 보여줍니다.

식료품점이 두 개의 개별 컬렉션에서 일대일 재고 및 영양 정보를 추적하는 다음 예를 생각해 보세요. 각 재고 항목은 고유한 영양 성분 항목에 해당합니다. nutrition_id 필드는 테이블 형식 데이터베이스와 유사하게 inventory 컬렉션을 nutrition_facts 컬렉션에 연결합니다.

// inventory collection
{
"name": "Pear",
"stock": 20,
"nutrition_id": 123, // reference to a nutrition_fact document
...
}
{
"name": "Candy Bar",
"stock": 26,
"nutrition_id": 456,
...
}
// nutrition_facts collection
{
"_id": 123,
"calories": 100,
"grams_sugar": 17,
"grams_protein": 1,
...
}
{
"_id": 456,
"calories": 250,
"grams_sugar": 27,
"grams_protein": 4,
...
}

애플리케이션이 name(으)로 재고 항목에 대한 영양 정보를 요청하는 경우, 이 스키마 구조는 재고 항목의 nutrition_id 와 일치하는 항목을 찾기 위해 nutrition_facts 컬렉션의 $lookup 가 필요합니다.

대신 inventory 컬렉션에 영양 정보를 포함할 수 있습니다.

// inventory collection
{
"name": "Pear",
"stock": 20,
"nutrition_facts": {
"calories": 100,
"grams_sugar": 17,
"grams_protein": 1,
...
}
...
}
{
"name": "Candy Bar",
"stock": 26,
"nutrition_facts": {
"calories": 250,
"grams_sugar": 27,
"grams_protein": 4,
...
}
...
}

이렇게 하면 inventory에서 항목을 쿼리할 때 다른 쿼리나 $lookup 작업 없이도 영양 정보가 결과에 포함됩니다. 컬렉션 전체의 데이터가 일대일 관계에 있는 경우 문서 포함을 고려하세요.

표 형식 데이터베이스와 유사하게 야구 리그의 players 컬렉션에 있는 문서가 teams 컬렉션에 있는 문서를 참조하는 다음 예를 생각해 보세요:

// players collection
{
"team_id": 1, // reference to a team document
"name": "Nick",
"position": "Pitcher"
...
}
{
"team_id": 1,
"name": "Anuj",
"position": "Shortstop"
...
}
// teams collection
{
"_id": 1,
"name": "Danbury Dolphins"
...
}

애플리케이션이 팀의 선수 목록을 요청하는 경우, 이 스키마 구조는 team_id 와 일치하는 각 선수를 찾기 위해 players 컬렉션의 $lookup 가 필요합니다.

대신 팀 문서 자체의 배열에 players을(를) 나열할 수 있습니다.

// teams collection
{
"_id": 1,
"name": "Danbury Dolphins",
"players": [
{
"name": "Nick",
"position": "Pitcher"
...
},
{
"name": "Anuj",
"position": "Shortstop"
...
}
]
}

배열을 사용하여 관련 데이터를 보유함으로써 애플리케이션은 $lookup 작업이나 다른 컬렉션에 대한 인덱스 없이도 해당 팀의 선수를 포함한 전체 team 정보를 검색할 수 있습니다. 이 경우 정보를 별도의 컬렉션에 저장하는 것보다 배열을 사용하는 것이 더 효율적입니다.

참고

위의 예에서 야구팀에는 정해진 수의 선수가 있으며 배열이 지나치게 커질 위험은 없습니다.

대규모 배열을 읽고 쓰는 데 드는 성능 비용은 $lookup 작업을 피함으로써 얻는 이점보다 클 수 있습니다. 배열이 제한되지 않거나 지나치게 큰 경우 해당 배열은 읽기 및 쓰기 성능을 저하시킬 수 있습니다.

배열에 인덱스를 생성하면 배열의 각 요소에 인덱스가 지정됩니다. 해당 배열에 자주 쓰면 잠재적으로 큰 배열 필드를 인덱싱하거나 다시 인덱싱하는 것은 중요할 수 있습니다.

다음도 참조하세요.

무제한 배열 피하기

스키마를 비정규화하는 것은 필드를 복제하거나 기존 필드에서 새 필드를 파생시키는 프로세스입니다. 비정규화는 다음과 같은 다양한 경우에 읽기 성능을 향상시킬 수 있습니다.

  • 반복 쿼리에는 다른 컬렉션에 있는 큰 문서의 몇 가지 필드가 필요합니다. 두 개의 서로 다른 컬렉션을 병합하거나 $lookup 작업을 자주 수행하지 않도록 반복 쿼리 대상 컬렉션의 내장된 문서에 해당 필드의 복사본을 유지하도록 선택할 수 있습니다.

  • collection에 있는 일부 필드의 평균 값이 요청되는 경우가 많습니다. 쓰기의 일부로 업데이트되고 해당 필드의 실행 평균을 유지 관리하는 별도의 collection에 파생된 필드를 생성하도록 선택할 수 있습니다.

관련 데이터를 그룹화할 때는 문서나 배열을 중복 없이 포함하는 것이 선호되지만, 별도의 collection을 유지해야 하는 경우에는 비정규화를 통해 읽기 성능을 개선할 수 있습니다.

참고

스키마를 비정규화하면 일관적인 중복 데이터를 유지 관리하는 것은 사용자의 책임이 됩니다.

스키마에 가장 적합한 구조는 애플리케이션의 컨텍스트에 따라 다릅니다. 다음 리소스에서는 데이터 모델링에 대한 자세한 정보와 내장된 문서 및 배열에 대한 사용 사례를 더 확인할 수 있습니다.

유연한 데이터 모델을 스키마에 통합하는 방법을 알아보려면 MongoDB.live 2020의 다음 프레젠테이션을 참조하세요:

  • MongoDB의엔티티 관계에 대해 알아보고, MongoDB를 사용한 데이터 모델링으로 구현한 예시를 살펴보세요.

  • 고급 스키마 설계 패턴을 통해 스키마에 통합할 수 있는 고급 데이터 모델링 디자인 패턴에 대해 알아보세요.

MongoDB에서 배열을 쿼리하는 방법에 대해 자세히 알아보려면 배열 쿼리를 참조하세요.

배열이 잘 작동하는 상황에 대해 알아보려면 다음 디자인 패턴을 참조하세요.

  • 각 영화가 일부 국가에서만 개봉하는 영화 데이터와 같이 고유한 속성 조합이 있는 데이터를 처리하려면 속성 패턴을 사용합니다.

  • 버킷 패턴은 시간 범위 데이터와 같이 긴밀하게 그룹화되거나 순차적인 데이터를 처리할 때 사용합니다.

  • 다형성 패턴을 사용하면 여러 스포츠 종목의 선수 기록과 같이 동일한 컬렉션에서 서로 다른 형태의 문서를 처리할 수 있습니다.

데이터를 복제하여 스키마를 개선하는 상황에 대해 읽어 보려면 다음 디자인 패턴을 참조하세요.

  • 확장 참조 패턴을 사용해 자주 읽는 데이터의 일부를 큰 문서에서 작은 문서로 복제할 수 있습니다.

돌아가기

스키마 개선