Поделиться через


Самостоятельные соединения — язык запросов в Cosmos DB (в Azure и Fabric)

На языке запросов данные свободны от схемы и обычно денормализованы. Вместо объединения данных между сущностями и наборами, например в реляционной базе данных, соединения происходят в одном элементе. В частности, соединения относятся к этому элементу и не могут выполняться в нескольких элементах и контейнерах.

Подсказка

Если вам нужно присоединиться к элементам и контейнерам, рассмотрите возможность повторной работы модели данных, чтобы избежать этого антишаблоны.

Самостоятельное присоединение к одному элементу

Рассмотрим пример самосоединения в элементе. Рассмотрим контейнер с одним элементом. Этот элемент представляет продукт с различными размерами:

[
  {
    "name": "Raiot Jacket",
    "sizes": [
      {
        "key": "s",
        "description": "Small"
      },
      {
        "key": "m",
        "description": "Medium"
      },
      {
        "key": "l",
        "description": "Large"
      },
      {
        "key": "xl",
        "description": "Extra Large"
      }
    ]
  }
]

Что делать, если вам нужно найти продукты с определенным размером? Как правило, необходимо написать запрос с фильтром, который проверяет каждый потенциальный индекс в массиве sizes для значения с префиксом. В этом примере запрос находит все продукты с размером, который заканчивается следующим Largeобразом:

SELECT
  *
FROM
  products p
WHERE
  p.sizes[0].description LIKE "%Large" OR
  p.sizes[1].description LIKE "%Large" OR
  p.sizes[2].description LIKE "%Large" OR
  p.sizes[3].description LIKE "%Large"

Этот метод может стать неприменимым быстро. Сложность или длина синтаксиса запроса увеличивает количество потенциальных элементов в массиве. Кроме того, этот запрос недостаточно гибкий для обработки будущих продуктов, которые могут иметь более трех размеров.

В традиционной реляционной базе данных размеры будут разделены на отдельную таблицу, а соединение между таблицами выполняется с фильтром, примененным к результатам. На языке запросов можно выполнить операцию самостоятельного соединения в элементе с помощью ключевого JOIN слова:

SELECT
  p.name,
  s.key,
  s.description
FROM
  products p
JOIN
  s in p.sizes

Этот запрос возвращает простой массив с элементом для каждого значения в массиве тегов.

[
  {
    "name": "Raiot Jacket",
    "key": "s",
    "description": "Small"
  },
  {
    "name": "Raiot Jacket",
    "key": "m",
    "description": "Medium"
  },
  {
    "name": "Raiot Jacket",
    "key": "l",
    "description": "Large"
  },
  {
    "name": "Raiot Jacket",
    "key": "xl",
    "description": "Extra Large"
  }
]

Давайте разберем запрос. Теперь запрос имеет два псевдонима: p для каждого элемента продукта в результирующем наборе и s для массива, присоединенного sizes к нему. Ключевое * слово допустимо только для проецировать все поля, если он может выводить входной набор, но теперь есть два входных набора (p и t). Из-за этого ограничения необходимо явно определить возвращаемые поля как name из продукта, так keyи description из размеров.

Наконец, можно использовать фильтр для поиска размеров, которые заканчиваются Large. Так как мы использовали ключевое JOIN слово, наш фильтр достаточно гибкий, чтобы обрабатывать любое переменное количество тегов:

SELECT
  p.name,
  s.key AS size
FROM
  products p
JOIN
  s in p.sizes
WHERE
  s.description LIKE "%Large"
[
  {
    "name": "Raiot Jacket",
    "size": "l"
  },
  {
    "name": "Raiot Jacket",
    "size": "xl"
  }
]

Самостоятельное присоединение нескольких элементов

Давайте перейдем к образцу, где необходимо найти значение в массиве, который существует в нескольких элементах. В этом примере рассмотрим контейнер с двумя элементами продукта. Каждый элемент содержит релевантные colors для этого элемента.

[
  {
    "name": "Gremon Fins",
    "colors": [
      "science-blue",
      "turbo"
    ]
  },
  {
    "name": "Elecy Jacket",
    "colors": [
      "indigo-shark",
      "jordy-blue-shark"
    ]
  },
  {
    "name": "Tresko Pack",
    "colors": [
      "golden-dream"
    ]
  }
]

Что делать, если вам нужно найти каждый элемент с цветом, который включает blue в имя? Вы можете выполнить поиск по строке blueвручную, но вам потребуется написать сложный запрос, который учитывает две характеристики этих элементов:

  • Цвета со blue подстрокой происходят по разным индексам в каждом массиве. Elecy Jacket Для продукта цвет является вторым элементом (индекс: 1). Gremon Fins Для продукта тег является первым элементом (индекс: 0). У Tresko Pack продукта нет никаких компонентов, содержащих эту подстроку.

  • Массив colors для каждого элемента имеет другую длину. И продукты оба имеют два цвета, в то время как Tresko Pack продукт имеет только один.Gremon FinsElecy Jacket

JOIN Здесь ключевое слово является отличным инструментом для создания кросс-продукта элементов и цветов. Соединения создают полный кросс-продукт наборов, участвующих в присоединении. Результатом является набор кортежей с каждой перемутацией элемента и значений в целевом массиве.

Операция соединения с примерами продуктов и цветов создает следующие элементы:

Продукт Цвет
Gremon Fins science-blue
Gremon Fins turbo
Elecy Jacket indigo-shark
Elecy Jacket jordy-blue-shark
Tresko Pack golden-dream

В этом примере запрос NoSQl использует ключевое JOIN слово для создания кросс-продукта и возвращает все перемутации:

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
[
  {
    "name": "Elecy Jacket",
    "color": "indigo-shark"
  },
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  },
  {
    "name": "Gremon Fins",
    "color": "turbo"
  },
  {
    "name": "Tresko Pack",
    "color": "golden-dream"
  }
]

Как и в случае с одним элементом, можно применить фильтр здесь, чтобы найти только элементы, соответствующие определенному тегу. Например, этот запрос находит все элементы со подстрокой, содержащейся blue в соответствии с первоначальным требованием, упомянутым ранее в этом разделе.

SELECT
  p.name,
  c AS color
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  {
    "name": "Elecy Jacket",
    "color": "jordy-blue-shark"
  },
  {
    "name": "Gremon Fins",
    "color": "science-blue"
  }
]

Этот запрос можно уточнить еще дальше, чтобы просто вернуть имена продуктов, которые соответствуют фильтру. Этот пример не проецит значения цвета, но фильтр по-прежнему работает должным образом:

SELECT VALUE
  p.name
FROM
  products p
JOIN
  c in p.colors
WHERE
  c LIKE "%blue%"
[
  "Elecy Jacket",
  "Gremon Fins"
]