다음을 통해 공유


자체 조인 - Cosmos DB의 쿼리 언어(Azure 및 패브릭)

쿼리 언어에서 데이터는 스키마가 없으며 일반적으로 비정규화됩니다. 관계형 데이터베이스에서처럼 엔터티 및 집합 간에 데이터를 조인하는 대신 조인은 단일 항목 내에서 발생합니다. 특히 조인은 해당 항목으로 범위가 지정되며 여러 항목 및 컨테이너에서 발생할 수 없습니다.

팁 (조언)

항목 및 컨테이너 간에 조인해야 하는 경우 이 안티패턴을 방지하기 위해 데이터 모델을 다시 작업하는 것이 좋습니다.

단일 항목으로 자체 조인

항목 내에서 자체 조인의 예를 살펴보겠습니다. 단일 항목이 있는 컨테이너를 고려합니다. 이 항목은 다양한 크기의 제품을 나타냅니다.

[
  {
    "name": "Raiot Jacket",
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      },
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  }
]

특정 크기의 제품을 찾아야 하는 경우 어떻게 해야 할까요? 일반적으로 접두사를 사용하는 값에 대한 배열의 모든 잠재적 인덱 sizes 스를 검사하는 필터가 있는 쿼리를 작성해야 합니다. 이 예제에서 쿼리는 다음으로 끝나는 크기의 모든 제품을 찾습니다 Large.

SELECT
  *
FROM
  products p
WHERE
  p.sizes[0].description LIKE "%Large" OR
  p.sizes[1].description LIKE "%Large" OR
  p.sizes[2].description LIKE "%Large" OR
  p.sizes[3].description LIKE "%Large"

이 기술은 신속하게 불가능해질 수 있습니다. 쿼리 구문의 복잡성 또는 길이는 배열의 잠재적 항목 수를 늘립니다. 또한 이 쿼리는 3개 이상의 크기를 가질 수 있는 향후 제품을 처리할 만큼 유연하지 않습니다.

기존 관계형 데이터베이스에서 크기는 별도의 테이블로 구분되고 결과에 적용된 필터를 사용하여 테이블 간 조인을 수행합니다. 쿼리 언어에서는 키워드를 사용하여 JOIN 항목 내에서 자체 조인 작업을 수행할 수 있습니다.

SELECT
  p.name,
  s.key,
  s.description
FROM
  products p
JOIN
  s in p.sizes

이 쿼리는 태그 배열의 각 값에 대한 항목이 있는 단순 배열을 반환합니다.

[
  {
    "name": "Raiot Jacket",
    "key": "s",
    "description": "Small"
  },
  {
    "name": "Raiot Jacket",
    "key": "m",
    "description": "Medium"
  },
  {
    "name": "Raiot Jacket",
    "key": "l",
    "description": "Large"
  },
  {
    "name": "Raiot Jacket",
    "key": "xl",
    "description": "Extra Large"
  }
]

쿼리를 세어보겠습니다. 이제 쿼리에는 결과 집합의 각 제품 항목과 s 자체 조인 배열에 대한 두 개의 별칭 psizes 있습니다. 키워드는 * 입력 집합을 유추할 수 있는 경우에만 모든 필드를 프로젝션하는 데 유효하지만, 이제 두 개의 입력 집합(pt)이 있습니다. 이 제약 조건으로 인해 반환된 필드를 name 제품과 함께 keydescription 및 크기에서 명시적으로 정의해야 합니다.

마지막으로 필터를 사용하여 .로 Large끝나는 크기를 찾을 수 있습니다. 키워드를 JOIN 사용했으므로 필터는 다양한 수의 태그를 처리할 수 있을 만큼 유연합니다.

SELECT
  p.name,
  s.key AS size
FROM
  products p
JOIN
  s in p.sizes
WHERE
  s.description LIKE "%Large"
[
  {
    "name": "Raiot Jacket",
    "size": "l"
  },
  {
    "name": "Raiot Jacket",
    "size": "xl"
  }
]

여러 항목 자체 조인

여러 항목에 있는 배열 내에서 값을 찾아야 하는 샘플로 이동해 보겠습니다. 이 예제에서는 두 개의 제품 항목이 있는 컨테이너를 고려합니다. 각 항목에는 해당 항목과 관련된 colors 항목이 포함됩니다.

[
  {
    "name": "Gremon Fins",
    "colors": [
      "science-blue",
      "turbo"
    ]
  },
  {
    "name": "Elecy Jacket",
    "colors": [
      "indigo-shark",
      "jordy-blue-shark"
    ]
  },
  {
    "name": "Tresko Pack",
    "colors": [
      "golden-dream"
    ]
  }
]

이름에 포함된 blue 색으로 모든 항목을 찾아야 하는 경우 어떻게 해야 할까요? 문자열 blue을 수동으로 검색할 수 있지만 다음 항목의 두 가지 특성을 고려하는 복잡한 쿼리를 작성해야 합니다.

  • 부분 문자열이 있는 blue 색은 각 배열의 다른 인덱스에서 발생합니다. Elecy Jacket 제품의 경우 색은 두 번째 항목(인덱스: 1)입니다. Gremon Fins 제품의 경우 태그는 첫 번째 항목(인덱스: 0)입니다. 제품에는 Tresko Pack 이 부분 문자열이 포함된 항목이 없습니다.

  • colors 각 항목의 배열 길이가 다릅니다. Gremon Fins 제품과 Elecy Jacket 제품은 모두 가지 색을 가지지만 제품에는 색이 Tresko Pack하나뿐입니다.

JOIN 여기서 키워드는 항목과 색의 교차 곱을 만드는 데 유용한 도구입니다. 조인은 조인에 참여하는 집합의 전체 교차 제품을 만듭니다. 그 결과 항목의 모든 순열과 대상 배열 내의 값이 포함된 튜플 집합이 생성됩니다.

샘플 제품 및 색에 대한 조인 작업은 다음 항목을 만듭니다.

제품 색깔
Gremon Fins science-blue
Gremon Fins turbo
Elecy Jacket indigo-shark
Elecy Jacket jordy-blue-shark
Tresko Pack golden-dream

이 예제 NoSQl 쿼리는 키워드를 JOIN 사용하여 교차 제품을 만들고 모든 순열을 반환합니다.

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
[
  {
    "name": "Elecy Jacket",
    "color": "indigo-shark"
  },
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  },
  {
    "name": "Gremon Fins",
    "color": "turbo"
  },
  {
    "name": "Tresko Pack",
    "color": "golden-dream"
  }
]

단일 항목과 마찬가지로 여기에서 필터를 적용하여 특정 태그와 일치하는 항목만 찾을 수 있습니다. 예를 들어 이 쿼리는 이 섹션의 앞부분에서 언급한 초기 요구 사항을 충족하기 위해 포함된 blue 부분 문자열이 있는 모든 항목을 찾습니다.

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  }
]

필터를 충족하는 제품의 이름을 반환하기 위해 이 쿼리를 더 구체화할 수 있습니다. 이 예제에서는 색 값을 프로젝터하지 않지만 필터는 여전히 예상대로 작동합니다.

SELECT VALUE
  p.name
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  "Elecy Jacket",
  "Gremon Fins"
]