Самостоятельное присоединение в Azure Cosmos DB для NoSQL
ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL
В Azure Cosmos DB для NoSQL данные являются свободными от схемы и обычно денормализованы. Вместо объединения данных между сущностями и наборами, например в реляционной базе данных, соединения происходят в одном элементе. В частности, соединения относятся к этому элементу и не могут выполняться в нескольких элементах и контейнерах.
Совет
Если вам нужно присоединиться к элементам и контейнерам, рассмотрите возможность повторной работы модели данных, чтобы избежать этого.
Самостоятельное присоединение к одному элементу
Рассмотрим пример самосоединения в элементе. Рассмотрим контейнер с одним элементом. Этот элемент представляет продукт с различными тегами:
[
{
"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"
}
]
}
]
Что делать, если вам нужно найти цветовую группу этого продукта? Как правило, необходимо написать запрос с проверкой каждого потенциального индекса в tags
массиве для значения с префиксом 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-")
Этот метод может стать неприменимым быстро. Сложность или длина синтаксиса запроса увеличивает количество потенциальных элементов в массиве. Кроме того, этот запрос недостаточно гибкий для обработки будущих продуктов, которые могут иметь более трех тегов.
В традиционной реляционной базе данных теги будут разделены на отдельную таблицу, а соединение между таблицами выполняется с фильтром, примененным к результатам. В API для NoSQL можно выполнить операцию самостоятельного соединения в элементе с помощью ключевого JOIN
слова.
SELECT
p.id,
p.sku,
t.slug
FROM
products p
JOIN
t IN p.tags
Этот запрос возвращает простой массив с элементом для каждого значения в массиве тегов.
[
{
"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"
}
]
Давайте разберем запрос. Теперь запрос имеет два псевдонима: p
для каждого элемента продукта в результирующем наборе и t
для массива, присоединенного tags
к нему. Ключевое *
слово допустимо только для проецировать все поля, если он может выводить входной набор, но теперь есть два входных набора (p
и t
). Из-за этого ограничения необходимо явно определить возвращаемые поля как id
и sku
из продукта вместе с slug
тегами. Чтобы упростить чтение и понимание этого запроса, можно удалить id
поле и использовать псевдоним для поля тега name
, чтобы переименовать его 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"
}
]
Наконец, можно использовать фильтр для поиска тега color-group-purple
. Так как мы использовали ключевое JOIN
слово, наш фильтр достаточно гибкий, чтобы обрабатывать любое переменное количество тегов.
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"
}
]
Самостоятельное присоединение нескольких элементов
Давайте перейдем к образцу, где необходимо найти значение в массиве, который существует в нескольких элементах. В этом примере рассмотрим контейнер с двумя элементами продукта. Каждый элемент содержит соответствующие теги для этого элемента.
[
{
"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"
}
]
}
]
Что если вам нужно найти каждый элемент с фигурой мумии мешок? Вы можете выполнить поиск тега bag-shape-mummy
, но вам потребуется написать сложный запрос, который учитывает две характеристики этих элементов:
Тег с
bag-shape-
префиксом возникает по разным индексам в каждом массиве. Для спящего мешка Vareno тег является третьим элементом (индекс:2
). Для спящего мешка Maresse тег является первым элементом (индекс:0
).Массив
tags
для каждого элемента имеет другую длину. Варено спящий мешок имеет два тега, в то время как Маресси спящий мешок имеет три.
JOIN
Здесь ключевое слово является отличным инструментом для создания кросс-продукта элементов и тегов. Соединения создают полный кросс-продукт наборов, участвующих в присоединении. Результатом является набор кортежей с каждой перемутацией элемента и значений в целевом массиве.
Операция соединения с нашим примером продуктов и тегов спящего мешка создает следующие элементы:
Товар | Тег |
---|---|
Маресси Спящий мешок (6') Мин | Форма сумки: мумия |
Маресси Спящий мешок (6') Мин | Изоляция сумки: вниз заливка |
Варено Спящий мешок (6') Турмерик | Изоляция мешка: синтетическая заливка |
Варено Спящий мешок (6') Турмерик | Группа цветов: желтый |
Варено Спящий мешок (6') Турмерик | Форма сумки: мумия |
Ниже приведен результирующий набор SQL-запросов и JSON для соединения, включающего несколько элементов в контейнер.
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"
}
]
Как и в случае с одним элементом, можно применить фильтр здесь, чтобы найти только элементы, соответствующие определенному тегу. Например, этот запрос находит все элементы с тегом с именем bag-shape-mummy
, чтобы соответствовать первоначальному требованию, упомянутому ранее в этом разделе.
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"
}
]
Вы также можете изменить фильтр, чтобы получить другой результирующий набор. Например, этот запрос находит все элементы с именем 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"
}
]