Udostępnij za pośrednictwem


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 dołączać 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.

Napiwek

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

Samosprzężenia z jednym elementem

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

[
  {
    "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 zrobić, jeśli chcesz znaleźć grupę kolorów tego produktu? Zazwyczaj należy napisać zapytanie, które ma filtr sprawdzający 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 stać się nie do utrzymania szybko. 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 for 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": "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"
  }
]

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ż kontener z dwoma elementami produktu. Każdy element zawiera odpowiednie tagi dla tego elementu.

[
  {
    "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 zrobić, jeśli trzeba znaleźć każdy element z kształtem torby mamo ? 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 przypadku śpiwora 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.

Tutaj JOIN słowo kluczowe jest doskonałym narzędziem do tworzenia krzyżowego produktu 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:

Towar Tag
Maresse Śpiwór (6') Ming Kształt torby: Mama
Maresse Śpiwór (6') Ming Izolacja worka: Wypełnienie w dół
Vareno Sleeping Bag (6') Kurkuma Izolacja torbowa: Wypełnienie syntetyczne
Vareno Sleeping Bag (6') Kurkuma Grupa kolorów: żółta
Vareno Sleeping Bag (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żesz 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"
  }
]