다음을 통해 공유


JSON 시작 - Cosmos DB의 쿼리 언어(Azure 및 패브릭)

JSON(JavaScript Object Notation)을 사용하는 것은 쿼리 언어의 핵심입니다. 항목은 JSON으로 저장되며 모든 쿼리, 식 및 형식은 JSON 데이터에서 작동하도록 설계되었습니다. JSON 자체에 대한 자세한 내용은 공식 JSON 사양을 참조하세요.

다음은 이 컨텍스트에서 JSON에 대해 알아야 할 몇 가지 주요 사항입니다.

  • JSON 개체는 항상 .로 { 시작하고 끝납니다 }.
  • 속성은 서로 내부에 중첩 될 수 있습니다.
  • 속성 값은 배열일 수 있습니다.
  • 속성 이름은 대/소문자를 구분합니다.
  • 속성 이름은 공백이나 특수 문자가 있는 문자열일 수도 있습니다.

중첩 속성

점 표기법을 사용하여 중첩된 JSON 속성에 액세스할 수 있습니다. 대부분의 프로그래밍 언어에서 속성에 액세스하는 것과 마찬가지로 작동합니다.

다음은 중첩된 JSON을 사용하는 예제 문서입니다.

[
  {
    "name": "Heatker Women's Jacket",
    "category": "apparel",
    "slug": "heatker-women-s-jacket",
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      }
    ],
    "metadata": {
      "link": "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
    }
  }
]

그런 다음 쿼리에서 동일한 중첩 속성을 프로젝스할 수 있습니다.

SELECT
  p.name,
  p.category,
  p.metadata.link
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"

그리고 다음과 같은 예상 출력을 얻을 수 있습니다.

[
  {
    "name": "Heatker Women's Jacket",
    "category": "apparel",
    "link": "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
  }
]

배열 및 집합

JSON은 배열을 지원하며 쿼리에서 작업할 수 있습니다. 특정 요소에 액세스하려면 배열에서 해당 위치를 사용합니다.

이전 섹션의 동일한 예제를 사용하여 해당 인덱스로 배열의 항목에 액세스할 수 있습니다. 예를 들어 배열의 첫 번째 항목에 액세스하려면 쿼리 언어의 0 배열에 대한 인덱스 시스템 (0부터 시작)이므로 인덱스를 사용합니다.

SELECT
  p.name,
  p.sizes[0].description AS defaultSize
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"

이 쿼리는 다음 JSON 개체를 생성합니다.

[
  {
    "name": "Heatker Women's Jacket",
    "defaultSize": "Small"
  }
]

이제 배열이 더 큰 예제를 살펴보겠습니다.

[
  {
    "name": "Vencon Kid's Coat",
    "category": "apparel",
    "slug": "vencon-kid-s-coat",
    "colors": [
      "cardinal",
      "disco"
    ],
    "sizes": [
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  }
]

종종 하위 쿼리 또는 자체 조인을 사용하여 배열의 모든 요소를 사용하려고 합니다. 예를 들어 각 색을 별도의 행으로 가져옵니다.

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c IN p.colors
WHERE
  p.name = "Vencon Kid's Coat"

그러면 다음과 같은 JSON 배열이 발생합니다.

[
  {
    "name": "Vencon Kid's Coat",
    "color": "cardinal"
  },
  {
    "name": "Vencon Kid's Coat",
    "color": "disco"
  }
]

배열에 특정 값이 있는지 확인하려면 키워드 뒤의 필터에서 배열을 WHERE 사용할 수 있습니다. 이 예제에서는 하위 쿼리 를 사용하여 배열의 항목을 필터링합니다.

SELECT VALUE
  p.name
FROM
  products p
WHERE
  EXISTS(SELECT VALUE
    c
  FROM
    c IN p.sizes
  WHERE
    c.description LIKE "%Large")

이 쿼리는 문자열의 플랫 JSON 배열을 생성합니다. 이 배열에는 예제의 항목이 포함됩니다.

[
  ...,
  "Vencon Kid's Coat"
  ...
]

마지막으로 여러 속성을 결합하여 배열을 생성할 수 있습니다. 이 예제에서는 여러 속성을 결합하여 배열을 형성합니다 metadata .

SELECT
  p.name,
  [
    p.category,
    p.slug,
    p.metadata.link
  ] AS metadata
FROM
  products p
WHERE
  p.name = "Heatker Women's Jacket"
[
  {
    "name": "Heatker Women's Jacket",
    "metadata": [
      "apparel",
      "heatker-women-s-jacket",
      "https://www.adventure-works.com/heatker-women-s-jacket/68719520138.p"
    ]
  }
]

반복

쿼리 언어는 원본의 키워드 FROM 를 사용하여 IN JSON 배열을 반복할 수 있습니다.

다음 예제 데이터 집합을 고려합니다.

[
  {
    "name": "Pila Swimsuit",
    "colors": [
      "regal-blue",
      "rose-bud-cherry"
    ],
    "sizes": [
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  },
  {
    "name": "Makay Bikini",
    "colors": [
      "starship"
    ],
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      },
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      }
    ]
  }
]

이 첫 번째 예제에서는 키워드를 IN 사용하여 각 제품에 대한 속성을 반복 colors 합니다.

SELECT
  *
FROM
  p IN p.colors
[
  "regal-blue",
  "rose-bud-cherry",
  "starship"
]

절을 사용하여 배열의 개별 항목을 필터링할 WHERE 수도 있습니다. 이 예제에서는 속성이 sizes 필터링됩니다.

SELECT
  p.key
FROM
  p IN p.sizes
WHERE
  p.description LIKE "%Large"
[
  {
    "key": "l"
  },
  {
    "key": "xl"
  },
  {
    "key": "l"
  }
]

동일한 IN 키워드를 사용하여 배열 반복 결과를 집계할 수 있습니다. 이 예제에서 쿼리는 컨테이너의 모든 항목에서 합산된 태그 수를 반환합니다.

SELECT VALUE
  COUNT(1)
FROM
  p IN p.sizes

비고

반복에 키워드를 IN 사용하는 경우 배열 외부의 속성을 필터링하거나 프로젝션할 수 없습니다. 대신 자체 조인을 사용합니다.

Null 및 정의되지 않은 값

문서에 속성이 없으면 해당 값은 .입니다 undefined. 속성이 있지만 설정된 null경우 명시적으로 설정된 값입니다. 구별 nullundefined 쿼리에서 혼동을 일으킬 수 있는 중요한 차이점입니다.

예를 들어 이 JSON 개체는 속성이 정의되지 않았기 때문에 속성의 undefinedsku 값을 갖습니다.

[
  {
    "name": "Witalica helmet",
    "category": "gear",
  }
]

속성이 정의되어 있지만 값 null 으로 설정되지 않았으므로 이 JSON 개체의 값은 동일한 속성에 대한 값입니다.

[
  {
    "name": "Witalica helmet",
    "category": "gear",
    "sku": null
  }
]

이러한 경우를 확인하는 기본 제공 함수가 있습니다.

  • IS_NULL 속성이 .인지 확인합니다 null.
  • IS_DEFINED 속성이 있는지 확인합니다(그렇지 않음 undefined).

두 가지 모두를 확인할 수 있는 방법은 다음과 같습니다.

SELECT
  IS_DEFINED(p.sku) AS isSkuDefined,
  IS_NULL(p.sku) AS isSkuDefinedButNull
FROM
  products p

대괄호 표기법

대부분의 예제에서는 표기법을 사용하여 속성을 지정하지만 대 괄호 표기법을 사용하여 항상 동일한 속성을 지정할 수 있습니다.

중첩된 개체를 속성 값 metadata 으로 사용하는 간단한 개체로 시작해 보겠습니다.

[
  {
    "name": "Hikomo Sandals",
    "metadata": {
      "link": "https://www.adventure-works.com/hikomo-sandals/68719519305.p"
    }
  }
]

해당 개체의 metadata.link 경우 대괄호 표기법의 조합을 사용하여 세 가지 방법으로 속성을 참조할 수 있습니다.

SELECT
  p.metadata.link AS metadataLinkDotNotation,
  p["metadata"]["link"] AS metadataLinkBracketNotation,
  p.metadata["link"] AS metadataLinkMixedNotation
FROM
  products p
WHERE
  p.name = "Hikomo Sandals"
[
  {
    "metadataLinkDotNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p",
    "metadataLinkBracketNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p",
    "metadataLinkMixedNotation": "https://www.adventure-works.com/hikomo-sandals/68719519305.p"
  }
]

팁 (조언)

속성 이름에 공백, 특수 문자 또는 예약어와 일치하는 경우 대괄호 표기법을 사용하여 속성을 지정해야 합니다.

JSON 식

쿼리 결과에서 직접 JSON 개체를 만들 수 있습니다. 이 JSON 배열을 예로 들어 보겠습니다.

[
  {
    "name": "Diannis Watch",
    "category": "apparel",
    "detailCategory": "apparel-accessories-watches",
    "slug": "diannis-watch",
    "sku": "64801",
    "price": 98,
    "quantity": 159
  },
  {
    "name": "Confira Watch",
    "category": "apparel",
    "detailCategory": "apparel-accessories-watches",
    "slug": "confira-watch",
    "sku": "64800",
    "price": 105,
    "quantity": 193
  }
]

가장 간단한 구문을 사용하면 NoSQL 쿼리에서 꺾쇠괄호({/}) 및 포함된 JSON 구문을 사용하여 상대적으로 평평한 JSON 개체의 속성 이름에 영향을 줄 수 있습니다.

SELECT {
  "brandName": p.name,
  "department": p.category
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "$1": {
      "brandName": "Diannis Watch",
      "department": "apparel"
    }
  },
  {
    "$1": {
      "brandName": "Confira Watch",
      "department": "apparel"
    }
  }
]

이전 예제에서는 명시적 이름이 $1 정의되지 않았기 때문에 결과에 유추된 이름이 있었습니다. 다음 예제에서는 결과에 별칭을 사용하여 정의된 명시적 이름이 product 있습니다.

SELECT {
  "brandName": p.name,
  "department": p.category
} AS product
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "product": {
      "brandName": "Diannis Watch",
      "department": "apparel"
    }
  },
  {
    "product": {
      "brandName": "Confira Watch",
      "department": "apparel"
    }
  }
]

또는 문에서 키워드 SELECT VALUEVALUE 사용하여 결과를 평면화할 수 있습니다.

SELECT VALUE {
  "brandName": p.name,
  "department": p.category
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "brandName": "Diannis Watch",
    "department": "apparel"
  },
  {
    "brandName": "Confira Watch",
    "department": "apparel"
  }
]

더 나아가 JSON 구문을 사용하여 원래 항목에 명시적으로 정의되지 않을 수 있는 배열, 하위 개체 및 기타 JSON 구문을 포함하도록 결과 JSON 개체를 "변형"할 수 있습니다. 이 기술은 클라이언트 애플리케이션이 기본 데이터와 일치하지 않는 특정 스키마의 데이터를 예상하는 경우에 유용합니다.

예를 들어 다음 JSON 스키마를 고려합니다.

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": [
    "id",
    "category",
    "financial"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "category": {
      "type": "object",
      "properties": {
        "department": {
          "type": "string"
        },
        "section": {
          "type": "string"
        }
      },
      "required": [
        "department"
      ]
    },
    "inventory": {
      "type": "object",
      "properties": {
        "stock": {
          "type": "number"
        }
      }
    },
    "financial": {
      "type": "object",
      "properties": {
        "listPrice": {
          "type": "number"
        }
      },
      "required": [
        "listPrice"
      ]
    }
  }
}

이 스키마는 다음 형식으로 구조화된 JSON 개체를 허용합니다.

[
  {
    "id": "[string]",
    "name": "[string]",
    "category": {
      "department": "[string]",
      "section": "[string]"
    },
    "inventory": {
      "stock": [number]
    },
    "financial": {
      "listPrice": [number]
    }
  }
]

이 NoSQL 쿼리는 이 새 스키마를 준수하도록 원래 개체를 다시 매핑합니다.

SELECT VALUE {
  "id": p.sku,
  "name": p.name,
  "category": {
    "department": p.category,
    "section": p.detailCategory
  },
  "inventory": {
    "stock": p.quantity
  },
  "financial": {
    "listPrice": p.price
  }
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-watches"
[
  {
    "id": "64801",
    "name": "Diannis Watch",
    "category": {
      "department": "apparel",
      "section": "apparel-accessories-watches"
    },
    "inventory": {
      "stock": 159
    },
    "financial": {
      "listPrice": 98
    }
  },
  {
    "id": "64800",
    "name": "Confira Watch",
    "category": {
      "department": "apparel",
      "section": "apparel-accessories-watches"
    },
    "inventory": {
      "stock": 193
    },
    "financial": {
      "listPrice": 105
    }
  }
]

컨테이너 별칭

기본적으로 키워드 후에 사용되는 용어는 FROM 쿼리의 대상인 컨테이너 를 참조합니다. 용어 자체는 컨테이너의 이름과 일치시킬 필요가 없습니다 .

예를 들어 컨테이너 이름이 지정된 products경우 해당 컨테이너가 쿼리의 대상인 한 이러한 쿼리 중 하나는 제대로 작동하고 모든 쿼리는 컨테이너를 참조 products 합니다.

SELECT
  products.id
FROM
  products
SELECT
  p.id
FROM
  p
SELECT
  items.id
FROM
  items
SELECT
  targetContainer.id
FROM
  targetContainer

NoSQL 쿼리를 보다 간결하게 만들기 위해 컨테이너 이름을 더 짧은 이름으로 별칭 지정하는 것이 일반적입니다. 별칭 지정은 다음 키워드를 AS 사용하여 수행할 수 있습니다.

SELECT
  p.id
FROM
  products AS p

쿼리 언어에는 키워드 없이 AS 대상 컨테이너의 참조 바로 후에 별칭을 정의할 수 있는 약식 구문도 있습니다. 이 약식은 키워드를 사용하는 AS 것과 기능적으로 동일합니다.

SELECT
  p.id
FROM
  products p

속성 별칭

동일한 AS 키워드로 정의된 별칭을 사용하여 결과의 필드 이름을 바꿀 수도 있습니다. 다음 몇 가지 예제에서는 이 샘플 데이터를 고려합니다.

[
  {
    "name": "Oceabelle Scarf",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p"
    }
  },
  {
    "name": "Shinity Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/shinity-socks/68719522161.p"
    }
  },
  {
    "name": "Horric Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "metadata": {
      "link": "https://www.adventure-works.com/horric-socks/68719522177.p"
    }
  }
]

이 첫 번째 예제에서는 metadataLink 속성 값에 별칭이 metadata.link 사용됩니다.

SELECT
  p.name,
  p.metadata.link AS metadataLink
FROM
  products p
[
  {
    "name": "Oceabelle Scarf",
    "metadataLink": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p"
  },
  {
    "name": "Shinity Socks",
    "metadataLink": "https://www.adventure-works.com/shinity-socks/68719522161.p"
  },
  {
    "name": "Horric Socks",
    "metadataLink": "https://www.adventure-works.com/horric-socks/68719522177.p"
  }
]

중요합니다

별칭을 사용하여 값을 공백, 특수 문자 또는 예약어와 함께 속성 이름으로 프로젝팅할 수 없습니다. 예를 들어 값의 프로젝션을 공백이 있는 속성 이름으로 변경하려면 JSON 식을 사용해야 합니다.

예를 들면 다음과 같습니다.

SELECT VALUE {
  "product name": p.name,
  "from": p.metadata.link,
  "detail/category": p.detailCategory
}
FROM
  products p
WHERE
  p.detailCategory = "apparel-accessories-scarfs-and-socks"
[
  {
    "product name": "Oceabelle Scarf",
    "from": "https://www.adventure-works.com/oceabelle-scarf/68719522190.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  },
  {
    "product name": "Shinity Socks",
    "from": "https://www.adventure-works.com/shinity-socks/68719522161.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  },
  {
    "product name": "Horric Socks",
    "from": "https://www.adventure-works.com/horric-socks/68719522177.p",
    "detail/category": "apparel-accessories-scarfs-and-socks"
  }
]

NoSQL 쿼리에 이름이 같은 속성이 두 개 있는 경우 별칭을 사용하여 속성 중 하나 또는 둘 다의 이름을 바꾸면 프로젝트된 결과에서 명확하게 알 수 있습니다.

다음 샘플 데이터를 고려합니다.

[
  {
    "name": "Oceabelle Scarf",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      {
        "key": "s"
      },
      ...
    ],
    "tags": [
      ...
    ]
  },
  {
    "name": "Shinity Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      ...
      {
        "key": "10"
      },
      ...
    ],
    "tags": [
      ...
      {
        "key": "length"
      }
    ]
  },
  {
    "name": "Horric Socks",
    "detailCategory": "apparel-accessories-scarfs-and-socks",
    "sizes": [
      ...
      {
        "key": "7"
      },
      ...
    ],
    "tags": [
      {
        "key": "fabric"
      },
      ...
    ]
  }
]

비고

이 샘플 데이터 및 쿼리 결과에서 간단히 하기 위해 여러 속성과 값이 제거되었습니다.

이 NoSQL 쿼리는 교차 제품 결과의 속성과 p.tags[].key 속성을 반환 p.sizes[].key 하지만 충돌을 방지하기 위해 각 key 속성의 별칭을 지정합니다.

SELECT
  p.name,
  s.key AS sizeKey,
  t.key AS tagKey
FROM
  products p
JOIN
  s IN p.sizes
JOIN
  t in p.tags
WHERE
  p.detailCategory = "apparel-accessories-scarfs-and-socks"
[
  {
    "name": "Oceabelle Scarf",
    "sizeKey": "s",
    "tagKey": "fabric"
  },
  ...
  {
    "name": "Shinity Socks",
    "sizeKey": "10",
    "tagKey": "length"
  },
  ...
  {
    "name": "Horric Socks",
    "sizeKey": "7",
    "tagKey": "fabric"
  }
]