Samoobslužná připojení 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 spojení dat mezi entitami a sadami, jako byste v relační databázi, došlo k spojení v rámci jedné položky. Spojení jsou konkrétně vymezena na danou položku a nemůžou nastat napříč několika položkami a kontejnery.

Tip

Pokud zjistíte, že se potřebujete spojit mezi položkami a kontejnery, zvažte přepracování datového modelu , abyste se tomu vyhnuli.

Spojení se svým držitelem s jednou položkou

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

[
  {
    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
    "categoryId": "bbbbbbbb-1111-2222-3333-cccccccccccc",
    "name": "Teapo Surfboard (6'10\") Grape",
    "sku": "teapo-surfboard-72109",
    "tags": [
      {
        "id": "cccccccc-2222-3333-4444-dddddddddddd",
        "slug": "tail-shape-swallow",
        "name": "Tail Shape: Swallow"
      },
      {
        "id": "dddddddd-3333-4444-5555-eeeeeeeeeeee",
        "slug": "length-inches-82",
        "name": "Length: 82 inches"
      },
      {
        "id": "eeeeeeee-4444-5555-6666-ffffffffffff",
        "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á kontrolu filtru pro každou potenciální index v tags poli pro 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 nepotenitelný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 spojení křížové tabulky se provádí s filtrem použitým na výsledky. V rozhraní API pro NoSQL můžeme pomocí klíčového slova provést operaci samoobslužného JOIN spojení v rámci položky.

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

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

[
  {
    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
    "sku": "teapo-surfboard-72109",
    "slug": "tail-shape-swallow"
  },
  {
    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
    "sku": "teapo-surfboard-72109",
    "slug": "length-inches-82"
  },
  {
    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
    "sku": "teapo-surfboard-72109",
    "slug": "color-group-purple"
  }
]

Pojďme dotaz rozdělit. Dotaz teď má dva aliasy: p pro každou položku produktu v sadě výsledků a t pro pole připojené tags k sobě. Klíčové * slovo je platné pouze pro projektovat všechna pole, pokud může odvodit vstupní sadu, ale nyní existují dvě vstupní sady (p a t). Kvůli tomuto omezení musíme explicitně definovat vrácená pole jako id a sku z produktu spolu se značkami slug . Abychom tomuto dotazu usnadnili čtení a porozumění, můžeme pole vypustit id a použít alias pro pole značky name k jeho přejmenování 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 k vyhledání značky color-group-purplepoužít filtr . Vzhledem k tomu, že jsme použili JOIN klíčové slovo, je náš filtr dostatečně flexibilní, aby zvládl libovolný počet proměnných 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"
  }
]

Připojení více položek k sobě

Pojďme přejít k ukázce, kde potřebujeme najít hodnotu v poli, která existuje ve více položkách. V tomto příkladu zvažte kontejner se dvěma položkami produktu. Každá položka obsahuje relevantní značky pro danou položku.

[
  {
    "id": "ffffffff-5555-6666-7777-aaaaaaaaaaaa",
    "categoryId": "cccccccc-8888-9999-0000-dddddddddddd",
    "categoryName": "Sleeping Bags",
    "name": "Maresse Sleeping Bag (6') Ming",
    "sku": "maresse-sleeping-bag-65503",
    "tags": [
      {
        "id": "b1b1b1b1-cccc-dddd-eeee-f2f2f2f2f2f2",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      },
      {
        "id": "bbbbbbbb-7777-8888-9999-cccccccccccc",
        "slug": "bag-insulation-down-fill",
        "name": "Bag Insulation: Down Fill"
      }
    ]
  },
  {
    "id": "c2c2c2c2-dddd-eeee-ffff-a3a3a3a3a3a3",
    "categoryId": "cccccccc-8888-9999-0000-dddddddddddd",
    "categoryName": "Sleeping Bags",
    "name": "Vareno Sleeping Bag (6') Turmeric",
    "sku": "vareno-sleeping-bag-65508",
    "tags": [
      {
        "id": "dddddddd-9999-0000-1111-eeeeeeeeeeee",
        "slug": "bag-insulation-synthetic-fill",
        "name": "Bag Insulation: Synthetic Fill"
      },
      {
        "id": "a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
        "slug": "color-group-yellow",
        "name": "Color Group: Yellow"
      },
      {
        "id": "b1b1b1b1-cccc-dddd-eeee-f2f2f2f2f2f2",
        "slug": "bag-shape-mummy",
        "name": "Bag Shape: Mummy"
      }
    ]
  }
]

Co když potřebujete najít každou položku s tvarem mummy tašky ? Můžete vyhledat značku bag-shape-mummy, ale budete muset napsat složitý dotaz, který odpovídá dvěma vlastnostem 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í tašku Vareno je značka třetí položkou (index: 2). Pro spací tašku Maresse je značka první položkou (index: 0).

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

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

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

Položka Značka
Maresse Spící taška (6') Ming Tvar tašky: Mummy
Maresse Spící taška (6') Ming Izolace tašky: Výplň dolů
Vareno Spací taška (6') Kurkuma Izolace sáčku: syntetické výplně
Vareno Spací taška (6') Kurkuma Skupina barev: Žlutá
Vareno Spací taška (6') Kurkuma Tvar tašky: Mummy

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 tady použít filtr, abyste našli jenom položky, které odpovídají určité značce. Tento dotaz například najde všechny položky se značkou s názvem 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ů. 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"
  }
]