Udostępnij za pomocą


Wprowadzenie do formatu JSON — język zapytań w usłudze Cosmos DB (na platformie Azure i w usłudze Fabric)

Praca z funkcją JavaScript Object Notation (JSON) jest sercem języka zapytań. Elementy są przechowywane jako dane JSON, a wszystkie zapytania, wyrażenia i typy są przeznaczone do pracy z danymi JSON. Aby uzyskać więcej informacji na temat samego formatu JSON, zobacz formalną specyfikację JSON.

Oto kilka kluczowych kwestii, które należy wiedzieć o formacie JSON w tym kontekście:

  • Obiekty JSON zawsze zaczynają się od { i kończą się na }.
  • Właściwości można zagnieżdżać wewnątrz siebie.
  • Wartości właściwości mogą być tablicami.
  • W nazwach właściwości jest rozróżniana wielkość liter.
  • Nazwy właściwości mogą być dowolnym ciągiem, nawet ze spacjami lub znakami specjalnymi.

Właściwości zagnieżdżone

Dostęp do zagnieżdżonych właściwości JSON można uzyskać przy użyciu notacji kropkowej. Działa to podobnie jak uzyskiwanie dostępu do właściwości w większości języków programowania.

Oto przykładowy dokument z zagnieżdżonym plikiem 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"
    }
  }
]

Następnie można projektować te same zagnieżdżone właściwości w zapytaniach:

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

Otrzymasz następujące oczekiwane dane wyjściowe:

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

Tablice i zestawy

Kod JSON obsługuje tablice i możesz z nimi pracować w zapytaniach. Aby uzyskać dostęp do określonego elementu, użyj jego pozycji w tablicy.

Korzystając z tego samego przykładu z poprzedniej sekcji, możemy uzyskać dostęp do elementu w tablicy przy użyciu jego indeksu. Jeśli na przykład chcemy uzyskać dostęp do pierwszego elementu w tablicy, użyjemy indeksu, ponieważ jest to system indeksów 0oparty na zera dla tablic w języku zapytań:

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

To zapytanie powoduje wyświetlenie następującego obiektu JSON:

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

Teraz rozważmy przykład z większą tablicą:

[
  {
    "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"
      }
    ]
  }
]

Często chcesz użyć podzapytania lub samosprzężenia do pracy ze wszystkimi elementami w tablicy. Aby na przykład pobrać każdy kolor jako oddzielny wiersz:

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

Co spowoduje, że tablica JSON będzie wyglądać następująco:

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

Aby sprawdzić, czy określona wartość istnieje w tablicy, możesz użyć tablicy w filtrze po słowie WHERE kluczowym. W tym przykładzie użyto podzapytania do filtrowania elementów tablicy:

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

To zapytanie powoduje utworzenie płaskiej tablicy ciągów w formacie JSON, która będzie zawierać element w przykładzie:

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

Na koniec można tworzyć tablice, łącząc wiele właściwości. W tym przykładzie wiele właściwości jest połączonych w celu utworzenia tablicy 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"
    ]
  }
]

Iteracja

Język zapytań obsługuje iterację na tablicach JSON przy użyciu słowa kluczowego INFROM w źródle.

Rozważmy ten przykładowy zestaw danych:

[
  {
    "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"
      }
    ]
  }
]

W tym pierwszym przykładzie użyto słowa kluczowego IN do wykonania iteracji nad właściwością colors dla każdego produktu:

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

Poszczególne wpisy w tablicy można również filtrować przy użyciu klauzuli WHERE . W tym przykładzie sizes właściwość jest filtrowana:

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

Używając tego samego IN słowa kluczowego, można agregować w wyniku iteracji tablicy. W tym przykładzie zapytanie zwraca liczbę tagów sumowanych we wszystkich elementach w kontenerze:

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

Uwaga / Notatka

W przypadku używania słowa kluczowego IN do iteracji nie można filtrować ani projektować żadnych właściwości poza tablicą. Zamiast tego należy używać sprzężeń własnych.

Wartości null i niezdefiniowane

Jeśli właściwość nie jest obecna w dokumencie, jej wartością jest undefined. Jeśli właściwość jest obecna, ale ustawiona na null, jest to jawnie ustawiona wartość. Rozróżnienie między elementami null i undefined jest ważnym rozróżnieniem, które może powodować zamieszanie w zapytaniach.

Na przykład ten obiekt JSON będzie miał wartość undefined dla sku właściwości, ponieważ właściwość nigdy nie została zdefiniowana:

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

Ten obiekt JSON miałby wartość null dla tej samej właściwości, ponieważ właściwość nie jest jeszcze ustawiona z wartością:

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

Istnieją wbudowane funkcje do sprawdzania następujących przypadków:

  • IS_NULL Sprawdza, czy właściwość ma wartość null.
  • IS_DEFINED sprawdza, czy właściwość istnieje (nie undefinedjest ).

Oto jak sprawdzić oba te elementy:

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

Notacja nawiasów kwadratowych

Podczas gdy większość przykładów używa notacji kropkowej do określania właściwości, zawsze można określić te same właściwości przy użyciu notacji nawiasów kwadratowych .

Zacznijmy od prostego obiektu z zagnieżdżonym obiektem jako wartością metadata właściwości:

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

Dla tego obiektu możemy odwoływać się do metadata.link właściwości na trzy różne sposoby przy użyciu kombinacji notacji kropkowej i nawiasu :

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"
  }
]

Wskazówka

Jeśli nazwa właściwości ma spacje, znaki specjalne lub pasuje do zastrzeżonego słowa, należy użyć notacji nawiasu, aby określić właściwość.

Wyrażenia JSON

Obiekty JSON można tworzyć bezpośrednio w wynikach zapytania. Zacznijmy od tej tablicy JSON jako przykładu:

[
  {
    "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
  }
]

Korzystając z najprostszej składni, można wpływać na nazwy właściwości stosunkowo płaskiego obiektu JSON przy użyciu nawiasów kątowych ({/}) i osadzonej składni JSON w zapytaniu NoSQL:

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"
    }
  }
]

W poprzednim przykładzie wynik miał wywnioskową nazwę $1 , ponieważ nie zdefiniowano jawnej nazwy. W następnym przykładzie wynik ma jawną nazwę product zdefiniowaną przy użyciu aliasu:

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"
    }
  }
]

Alternatywnie wynik można spłaszczać przy użyciu słowa kluczowego VALUE w instrukcji SELECT VALUE :

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"
  }
]

Jeszcze bardziej szczegółowo możesz użyć składni JSON, aby "ponownie zdefiniować" wynikowy obiekt JSON w celu uwzględnienia tablic, podobiektów i innych konstrukcji JSON, które mogą nie być jawnie zdefiniowane w oryginalnym elemencie. Ta technika jest przydatna, jeśli aplikacja kliencka oczekuje danych w określonym schemacie, który nie pasuje do danych bazowych.

Rozważmy ten schemat JSON, na przykład:

{
  "$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"
      ]
    }
  }
}

Ten schemat zezwala na ustrukturyzowany obiekt JSON w tym formacie:

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

To zapytanie NoSQL ponownie mapuje oryginalny obiekt[s], aby był zgodny z tym nowym schematem:

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
    }
  }
]

Aliasy kontenerów

Domyślnie termin używany po słowie FROM kluczowym odwołuje się do kontenera , który jest obiektem docelowym zapytania. Sam termin NIE jest wymagany do dopasowania nazwy kontenera.

Jeśli na przykład kontener ma nazwę products, dowolne z tych zapytań działa prawidłowo i wszystkie odwołują się do products kontenera tak długo, jak ten kontener jest obiektem docelowym zapytania:

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

Aby zapytanie NoSQL było bardziej zwięzłe, często aliasuje nazwę kontenera o krótszej nazwie. Aliasowanie można wykonać przy użyciu słowa kluczowego AS :

SELECT
  p.id
FROM
  products AS p

Język zapytań ma również skróconą składnię, w której alias można zdefiniować natychmiast po odwołaniu kontenera docelowego bez słowa kluczowego AS . Ten skrót jest funkcjonalnie równoważny z użyciem słowa kluczowego AS :

SELECT
  p.id
FROM
  products p

Aliasy właściwości

Możesz również zmienić nazwy pól w wynikach przy użyciu aliasów definiowanych za pomocą tego samego AS słowa kluczowego. W kilku następnych przykładach rozważ następujące przykładowe dane:

[
  {
    "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"
    }
  }
]

W tym pierwszym przykładzie metadataLink alias jest używany dla metadata.link wartości właściwości:

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"
  }
]

Ważne

Nie można używać aliasu do projekcji wartości jako nazwy właściwości z spacją, znakiem specjalnym lub słowem zarezerwowanym. Jeśli na przykład chcesz zmienić projekcję wartości na , aby mieć nazwę właściwości z spacją, musisz użyć wyrażenia JSON.

Na przykład

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"
  }
]

Jeśli zapytanie NoSQL ma dwie właściwości o tej samej nazwie, użyj aliasów, aby zmienić nazwę jednej lub obu właściwości, aby były one uściślane w przewidywanym wyniku.

Rozważ następujące przykładowe dane:

[
  {
    "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"
      },
      ...
    ]
  }
]

Uwaga / Notatka

W tych przykładowych danych i wyniku zapytania usunięto wiele właściwości i wartości w celu zwięzłości.

To zapytanie NoSQL zwraca p.sizes[].key właściwości i p.tags[].key w wyniku między produktami, ale aliasuje każdą key właściwość, aby uniknąć kolizji:

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"
  }
]