Sdílet prostřednictvím


Začínáme s JSON – Dotazovací jazyk ve službě Cosmos DB (v Azure a Prostředcích infrastruktury)

Práce s JavaScript Object Notation (JSON) je jádrem dotazovacího jazyka. Položky se ukládají jako JSON a všechny dotazy, výrazy a typy jsou navržené tak, aby fungovaly s daty JSON. Další informace o samotném formátu JSON najdete ve formální specifikaci JSON.

Tady je několik klíčových věcí, které je potřeba vědět o formátu JSON v tomto kontextu:

  • Objekty JSON vždy začínají { a končí na }.
  • Vlastnosti se dají vnořit do sebe.
  • Hodnoty vlastností mohou být matice.
  • V názvech vlastností se rozlišují malá a velká písmena.
  • Názvy vlastností můžou být libovolný řetězec, a to i s mezerami nebo speciálními znaky.

Vnořené vlastnosti

K vnořeným vlastnostem JSON můžete přistupovat pomocí zápisu tečky. To funguje stejně jako přístup k vlastnostem ve většině programovacích jazyků.

Tady je ukázkový dokument s vnořeným kódem 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"
    }
  }
]

Pak můžete v dotazech promítt stejné vnořené vlastnosti:

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

A tento očekávaný výstup byste získali:

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

Pole a sady

JSON podporuje pole a v dotazech s nimi můžete pracovat. Pokud chcete získat přístup ke konkrétnímu prvku, použijte jeho pozici v poli.

Pomocí stejného příkladu z předchozí části můžeme získat přístup k položce v poli pomocí jeho indexu. Pokud například chceme získat přístup k první položce v poli, použijeme index 0 , protože se jedná o systém indexů založený na nule pro pole v dotazovacím jazyce:

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

Výsledkem tohoto dotazu je následující objekt JSON:

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

Teď se podíváme na příklad s větším polem:

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

Často chcete použít poddotaz nebo vlastní spojení, abyste mohli pracovat se všemi prvky v poli. Pokud chcete například získat každou barvu jako samostatný řádek:

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

Výsledkem by bylo pole JSON takto:

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

Pokud chcete zkontrolovat, jestli v poli existuje určitá hodnota, můžete pole použít ve filtru za klíčovým slovem WHERE . Tento příklad používá poddotaz k filtrování položek pole:

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

Výsledkem tohoto dotazu je ploché pole řetězců JSON, které by zahrnovaly položku v příkladu:

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

Nakonec můžete vytvořit pole zkombinováním více vlastností. V tomto příkladu se k vytvoření metadata pole zkombinuje více vlastností:

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

Iterace

Dotazovací jazyk podporuje iteraci polí JSON pomocí klíčového IN slova ve zdroji FROM .

Podívejte se na tuto ukázku datové sady:

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

Tento první příklad používá IN klíčové slovo k provedení iterace vlastnosti colors pro každý produkt:

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

Jednotlivé položky v poli můžete filtrovat také pomocí WHERE klauzule. V tomto příkladu sizes je vlastnost filtrována:

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

Pomocí stejného IN klíčového slova můžete agregovat výsledek iterace pole. V tomto příkladu dotaz vrátí počet značek sečtených napříč všemi položkami v kontejneru:

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

Poznámka:

Při použití klíčového IN slova pro iteraci nemůžete filtrovat ani projektovat žádné vlastnosti mimo pole. Místo toho použijete samoobslužná spojení.

Hodnoty null a nedefinované hodnoty

Pokud vlastnost v dokumentu není, její hodnota je undefined. Pokud je vlastnost přítomna, ale nastavena na null, to je explicitně nastavená hodnota. Rozdíl mezi null dotazy a undefined je důležitým rozdílem, který může způsobit nejasnosti v dotazech.

Například tento objekt JSON by měl hodnotu undefined pro sku vlastnost, protože vlastnost nebyla nikdy definována:

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

Tento objekt JSON by měl hodnotu null pro stejnou vlastnost, protože vlastnost je ještě definována s hodnotou:

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

Existují integrované funkce, které můžete zkontrolovat v těchto případech:

  • IS_NULL zkontroluje, zda je nullvlastnost .
  • IS_DEFINED zkontroluje, jestli vlastnost existuje (není undefined).

Tady je postup, jak zkontrolovat obojí:

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

Zápis závorek

I když většina příkladů k určení vlastností používá tečku , můžete vždy zadat stejné vlastnosti pomocí zápisu závorek .

Začněme jednoduchým objektem s vnořeným objektem jako hodnotou metadata vlastnosti:

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

Pro tento objekt můžeme na vlastnost odkazovat metadata.link třemi různými způsoby pomocí kombinací tečky a zápisu závorek :

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

Návod

Pokud název vlastnosti obsahuje mezery, speciální znaky nebo odpovídá vyhrazenému slovu, musíte k zadání vlastnosti použít zápis závorek.

Výrazy JSON

Objekty JSON můžete vytvářet přímo ve výsledcích dotazu. Začněme tímto polem JSON jako příkladem:

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

Pomocí nejjednodušší syntaxe můžete ovlivnit názvy vlastností relativně plochého objektu JSON pomocí úhlových závorek ({/}) a vložené syntaxe JSON v dotazu 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"
    }
  }
]

V předchozím příkladu měl výsledek odvozený název $1 , protože explicitní název nebyl definován. V tomto dalším příkladu má výsledek explicitní název product definovaný pomocí 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"
    }
  }
]

Výsledek lze také zploštět pomocí klíčového VALUESELECT VALUE slova v příkazu:

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

Ještě dál můžete pomocí syntaxe JSON "změnit tvar" výsledného objektu JSON tak, aby zahrnoval pole, podobjekty a další konstrukty JSON, které nemusí být explicitně definovány v původní položce. Tato technika je užitečná, pokud klientská aplikace očekává data v určitém schématu, které neodpovídá podkladovým datům.

Představte si toto schéma JSON, například:

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

Toto schéma by umožnilo objekt JSON strukturovaný v tomto formátu:

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

Tento dotaz NoSQL přemapuje původní objekty tak, aby vyhovovaly tomuto novému schématu:

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 kontejnerů

Ve výchozím nastavení termín použitý za FROM klíčovým slovem odkazuje na kontejner , který je cílem dotazu. Samotný termín se nevyžaduje , aby odpovídal názvu kontejneru.

Pokud je například kontejner pojmenovaný products, všechny tyto dotazy fungují správně a všechny odkazují na products kontejner, pokud je tento kontejner cílem dotazu:

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

Pokud chcete, aby byl dotaz NoSQL výstižnější, je běžné aliasovat název kontejneru kratším názvem. Aliasing je možné provést pomocí klíčového AS slova:

SELECT
  p.id
FROM
  products AS p

Dotazovací jazyk má také zkrácenou syntaxi, kde lze alias definovat hned za odkazem cílového kontejneru bez klíčového AS slova. Tato zkratka je funkčně ekvivalentní použití klíčového AS slova:

SELECT
  p.id
FROM
  products p

Aliasy vlastností

Pole ve výsledcích můžete také přejmenovat pomocí aliasů definovaných stejným AS klíčovým slovem. V následujících několika příkladech zvažte tato ukázková data:

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

V tomto prvním příkladu metadataLink se alias používá pro metadata.link hodnotu vlastnosti:

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

Důležité

Aliasing nemůžete použít k promítání hodnoty jako názvu vlastnosti s mezerou, speciálním znakem nebo vyhrazeným slovem. Pokud chcete změnit projekci hodnoty na název vlastnosti s mezerou, musíte použít výraz JSON.

Příklad:

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

Pokud má dotaz NoSQL dvě vlastnosti se stejným názvem, pomocí aliasů přejmenujte jednu nebo obě vlastnosti, aby byly v předpokládaném výsledku nejednoznačné.

Podívejte se na tato ukázková data:

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

Poznámka:

V těchto ukázkových datech a výsledku dotazu bylo kvůli stručnosti odebráno více vlastností a hodnot.

Tento dotaz NoSQL vrátí p.sizes[].key vlastnosti a p.tags[].key vlastnosti ve výsledku mezi produkty, ale bude každou key vlastnost aliasovat, aby nedocházelo ke kolizím:

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