Připojení sama ve službě Azure Cosmos DB for NoSQL

PLATÍ PRO: NoSQL

Ve službě Azure Cosmos DB for NoSQL jsou data bez schématu a obvykle denormalizovaná. Místo spojování dat mezi entitami a sadami, jako byste to dělali v relační databázi, dochází ke spojení v rámci jedné položky. Konkrétně jsou spojení vymezená na danou položku a nemůžou se vyskytovat ve více položkách a kontejnerech.

Tip

Pokud zjistíte, že potřebujete spojit položky a kontejnery, zvažte přepracování datového modelu , abyste tomu předešli.

Samoobslužné spojení s jednou položkou

Podívejme se na příklad spojení sama v rámci položky. Představte si kontejner s jednou položkou. Tato položka představuje produkt s různými značkami:

[
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "categoryId": "e592b992-d453-42ee-a74e-0de2cc97db42",
    "name": "Teapo Surfboard (6'10\") Grape",
    "sku": "teapo-surfboard-72109",
    "tags": [
      {
        "id": "556dc4f5-1dbd-41dc-9674-fda626e5d15c",
        "slug": "tail-shape-swallow",
        "name": "Tail Shape: Swallow"
      },
      {
        "id": "ac097b9a-8a30-4fd1-8cb6-69d3388ee8a2",
        "slug": "length-inches-82",
        "name": "Length: 82 inches"
      },
      {
        "id": "ce62b524-8e96-4999-b3e1-61ae7a672e2e",
        "slug": "color-group-purple",
        "name": "Color Group: Purple"
      }
    ]
  }
]

Co když potřebujete najít skupinu barev tohoto produktu? Obvykle byste museli napsat dotaz, který má filtr, který kontroluje každý potenciální index v tags poli hodnotu s předponou color-group-.

SELECT
  * 
FROM
  products p
WHERE
  STARTSWITH(p.tags[0].slug, "color-group-") OR
  STARTSWITH(p.tags[1].slug, "color-group-") OR
  STARTSWITH(p.tags[2].slug, "color-group-")

Tato technika se může rychle stát neobsaditelným. Složitost nebo délka syntaxe dotazu zvyšuje počet potenciálních položek v poli. Tento dotaz navíc není dostatečně flexibilní pro zpracování budoucích produktů, které můžou mít více než tři značky.

V tradiční relační databázi by se značky rozdělily do samostatné tabulky a křížové spojení mezi tabulkami se provede s filtrem použitým na výsledky. V rozhraní API pro NoSQL můžeme provést operaci samoobslužného připojení v rámci položky pomocí klíčového JOIN slova .

SELECT
  p.id,
  p.sku,
  t.slug
FROM
  products p
JOIN
  t IN p.tags

Tento dotaz vrátí jednoduché pole s položkou pro každou hodnotu v poli značek.

[
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "tail-shape-swallow"
  },
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "length-inches-82"
  },
  {
    "id": "863e778d-21c9-4e2a-a984-d31f947c665c",
    "sku": "teapo-surfboard-72109",
    "slug": "color-group-purple"
  }
]

Pojďme si dotaz rozepsat. Dotaz teď má dva aliasy: p pro každou položku produktu v sadě výsledků dotazu a t pro pole připojené tags k sobě. Klíčové * slovo je platné pouze pro promítání všech polí, pokud dokáže odvodit vstupní sadu, ale teď existují dvě vstupní sady (p a t). Kvůli tomuto omezení musíme naše vrácená pole explicitně definovat jako id a sku z produktu společně se značkami slug . Aby byl tento dotaz čitelnější a srozumitelnější, můžeme pole vypustit id a pomocí aliasu pro pole značky ho name přejmenovat na tag.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
[
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Tail Shape: Swallow"
  },
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Length: 82 inches"
  },
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Color Group: Purple"
  }
]

Nakonec můžeme použít filtr k vyhledání značky color-group-purple. Vzhledem k tomu, že jsme použili JOIN klíčové slovo, je náš filtr dostatečně flexibilní, aby mohl zpracovat libovolný proměnný počet značek.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  STARTSWITH(t.slug, "color-group-")
[
  {
    "sku": "teapo-surfboard-72109",
    "tag": "Color Group: Purple"
  }
]

Automatické spojování více položek

Přejděme k ukázce, kde potřebujeme najít hodnotu v rámci pole, které existuje ve více položkách. V tomto příkladu si představte kontejner se dvěma položkami produktu. Každá položka obsahuje relevantní značky pro danou položku.

[
  {
    "id": "80d62f31-9892-48e5-9b9b-5714d551b8b3",
    "categoryId": "19cd9b93-bdc5-4082-97fe-2c80c2fd77dd",
    "categoryName": "Sleeping Bags",
    "name": "Maresse Sleeping Bag (6') Ming",
    "sku": "maresse-sleeping-bag-65503",
    "tags": [
      {
        "id": "f50f3ee1-e150-4821-922b-ebe6ad82f313",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      },
      {
        "id": "8564fb66-63ea-464a-872a-7598433b9479",
        "slug": "bag-insulation-down-fill",
        "name": "Bag Insulation: Down Fill"
      }
    ]
  },
  {
    "id": "6e9f51c1-6b45-440f-af5a-2abc96cd083d",
    "categoryId": "19cd9b93-bdc5-4082-97fe-2c80c2fd77dd",
    "categoryName": "Sleeping Bags",
    "name": "Vareno Sleeping Bag (6') Turmeric",
    "sku": "vareno-sleeping-bag-65508",
    "tags": [
      {
        "id": "e02502ce-367e-4fb4-940e-93d994fa6062",
        "slug": "bag-insulation-synthetic-fill",
        "name": "Bag Insulation: Synthetic Fill"
      },
      {
        "id": "c0844995-3db9-4dbb-8d9d-d2c2a6151b94",
        "slug": "color-group-yellow",
        "name": "Color Group: Yellow"
      },
      {
        "id": "f50f3ee1-e150-4821-922b-ebe6ad82f313",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      }
    ]
  }
]

Co když potřebujete najít všechny položky s tvarem mumie tašky ? Mohli byste vyhledat značku bag-shape-mummy, ale museli byste napsat složitý dotaz, který počítá se dvěma charakteristikami těchto položek:

  • Značka s předponou bag-shape- se vyskytuje v různých indexech v každém poli. Pro spací pytel Vareno je značka třetí položkou (index: 2). Pro spacák Maresse je značka první položkou (index: 0).

  • Pole tags pro každou položku má jinou délku. Spací pytel Vareno má dvě značky, zatímco spacák Maresse má tři.

JOIN Klíčové slovo je zde skvělým nástrojem pro vytvoření křížového produktu položek a značek. Spojení vytvoří kompletní křížový produkt sad, které se spojení účastní. Výsledkem je sada řazených kolekcí členů s každou permutací položky a hodnotami v rámci cílového pole.

Operace spojení na našich ukázkových spacácích a značkách vytvoří následující položky:

Položka Značka
Maresse spací pytel (6') Ming Taška tvar: Mumie
Maresse spací pytel (6') Ming Izolace sáčku: Výplň dolů
Vareno spací pytel (6') Kurkuma Izolace sáčku: syntetická výplň
Vareno spací pytel (6') Kurkuma Skupina barev: Žlutá
Vareno spací pytel (6') Kurkuma Taška tvar: Mumie

Tady je dotaz SQL a sada výsledků JSON pro spojení, které obsahuje více položek v kontejneru.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags"
[
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Shape: Mummy"
  },
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Insulation: Down Fill"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Insulation: Synthetic Fill"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Color Group: Yellow"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Shape: Mummy"
  }
]

Stejně jako u jedné položky můžete i tady pomocí filtru najít jenom položky, které odpovídají určité značce. Tento dotaz například najde všechny položky se značkou, bag-shape-mummy která splňuje počáteční požadavek uvedený výše v této části.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags" AND
  t.slug = "bag-shape-mummy"
[
  {
    "sku": "maresse-sleeping-bag-65503",
    "tag": "Bag Shape: Mummy"
  },
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Shape: Mummy"
  }
]

Filtr můžete také změnit tak, aby získal jinou sadu výsledků dotazu. Tento dotaz například najde všechny položky, které mají značku s názvem bag-insulation-synthetic-fill.

SELECT
  p.sku,
  t.name AS tag
FROM
  products p
JOIN
  t IN p.tags
WHERE
  p.categoryName = "Sleeping Bags" AND
  t.slug = "bag-insulation-synthetic-fill"
[
  {
    "sku": "vareno-sleeping-bag-65508",
    "tag": "Bag Insulation: Synthetic Fill"
  }
]