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