Samosprzężenia w usłudze Azure Cosmos DB for NoSQL

DOTYCZY: NoSQL

W usłudze Azure Cosmos DB for NoSQL dane są wolne od schematu i zwykle zdenormalizowane. Zamiast łączyć dane między jednostkami i zestawami, tak jak w relacyjnej bazie danych, sprzężenia występują w jednym elemencie. W szczególności sprzężenia są ograniczone do tego elementu i nie mogą występować w wielu elementach i kontenerach.

Porada

Jeśli okaże się, że potrzebujesz sprzężenia między elementami i kontenerami, rozważ przerobienie modelu danych , aby tego uniknąć.

Samosprzężenia z pojedynczym elementem

Przyjrzyjmy się przykładowi samosprzężenia w elemencie. Rozważ kontener z jednym elementem. Ten element reprezentuje produkt z różnymi tagami:

[
  {
    "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 zrobić, jeśli chcesz znaleźć grupę kolorów tego produktu? Zazwyczaj należy napisać zapytanie z filtrem sprawdzającym każdy potencjalny indeks w tags tablicy pod kątem wartości z prefiksem 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-")

Ta technika może szybko stać się nie do utrzymania. Złożoność lub długość składni zapytania zwiększa liczbę potencjalnych elementów w tablicy. Ponadto to zapytanie nie jest wystarczająco elastyczne, aby obsługiwać przyszłe produkty, które mogą mieć więcej niż trzy tagi.

W tradycyjnej relacyjnej bazie danych tagi zostaną rozdzielone na oddzielną tabelę, a sprzężenie między tabelami jest wykonywane z filtrem zastosowanym do wyników. W interfejsie API dla NoSQL możemy wykonać operację samosprzężenia w elemencie przy użyciu słowa kluczowego JOIN .

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

To zapytanie zwraca prostą tablicę z elementem dla każdej wartości w tablicy tagów.

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

Przeanalizujmy zapytanie. Zapytanie ma teraz dwa aliasy: p dla każdego elementu produktu w zestawie wyników i t dla tablicy sprzężonej tags samodzielnie. Słowo * kluczowe jest prawidłowe tylko do projekcji wszystkich pól, jeśli może wywnioskować zestaw danych wejściowych, ale teraz istnieją dwa zestawy danych wejściowych (p i t). Ze względu na to ograniczenie musimy jawnie zdefiniować zwracane pola jako id i sku z produktu wraz z tagami slug . Aby ułatwić odczytywanie i zrozumienie tego zapytania, możemy usunąć id pole i użyć aliasu dla pola tagu name , aby zmienić jego nazwę 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"
  }
]

Na koniec możemy użyć filtru, aby znaleźć tag color-group-purple. Ponieważ użyliśmy słowa kluczowego JOIN , nasz filtr jest wystarczająco elastyczny, aby obsłużyć dowolną zmienną liczbę tagów.

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

Samosądanie wielu elementów

Przejdźmy do przykładu, w którym musimy znaleźć wartość w tablicy, która istnieje w wielu elementach. W tym przykładzie rozważmy kontener z dwoma elementami produktu. Każdy element zawiera odpowiednie tagi dla tego elementu.

[
  {
    "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 zrobić, jeśli chcesz znaleźć każdy element z kształtem torby mumii ? Możesz wyszukać tag bag-shape-mummy, ale musisz napisać złożone zapytanie, które odpowiada dwóm cechom tych elementów:

  • Tag z prefiksem bag-shape- występuje w różnych indeksach w każdej tablicy. W przypadku śpiwora Vareno tag jest trzecim elementem (indeks: 2). W śpiworce Maresse tag jest pierwszym elementem (indeks: 0).

  • Tablica tags dla każdego elementu ma inną długość. Śpiwór Vareno ma dwa tagi, podczas gdy śpiwór Maresse ma trzy.

JOIN W tym miejscu słowo kluczowe jest doskonałym narzędziem do tworzenia produktu krzyżowego elementów i tagów. Sprzężenia tworzą kompletny produkt krzyżowy zestawów uczestniczących w sprzężeniu. Wynik jest zestawem krotki z każdą permutacją elementu i wartościami w tablicy docelowej.

Operacja sprzężenia na naszych przykładowych produktach śpiwórki i tagach tworzy następujące elementy:

Element Tag
Maresse Śpiwór (6') Ming Kształt torby: Mama
Maresse Śpiwór (6') Ming Izolacja worka: Wypełnienie w dół
Vareno Śpiwór (6') Kurkuma Izolacja worka: wypełnienie syntetyczne
Vareno Śpiwór (6') Kurkuma Grupa kolorów: żółty
Vareno Śpiwór (6') Kurkuma Kształt torby: Mama

Oto zapytanie SQL i zestaw wyników JSON dla sprzężenia zawierającego wiele elementów w kontenerze.

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

Podobnie jak w przypadku pojedynczego elementu, można zastosować tutaj filtr, aby znaleźć tylko elementy pasujące do określonego tagu. Na przykład to zapytanie znajduje wszystkie elementy z tagiem o nazwie bag-shape-mummy , aby spełnić początkowe wymaganie wymienione wcześniej w tej sekcji.

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

Możesz również zmienić filtr, aby uzyskać inny zestaw wyników. Na przykład to zapytanie znajduje wszystkie elementy, które mają tag o nazwie 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"
  }
]