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


Управление индексированием в Azure DocumentDB

Индексы — это структуры, которые повышают скорость извлечения данных, предоставляя быстрый доступ к полям в коллекции. Они работают путем создания упорядоченного набора указателей на данные, часто основанные на ключевых полях. Azure DocumentDB использует индексы в нескольких контекстах, включая отправку запросов, уникальные ограничения и сегментирование.

Это важно

Поле "_id" — это единственное поле, индексированное по умолчанию, и максимальный размер поля может быть 2 KB. Рекомендуется добавить дополнительные индексы на основе фильтров запросов и предикатов для оптимизации производительности.

Типы индексов

Для простоты рассмотрим пример приложения блога со следующей настройкой:

  • Имя базы данных: cosmicworks
  • Имя коллекции: products

В этом примере приложения хранятся статьи в виде документов со следующей структурой. В приведенном ниже примере используется структура этой коллекции.

{
  "_id": ObjectId("617a34e7a867530bff1b2346"),
  "title": "Azure DocumentDB - A Game Changer",
  "content": "Azure DocumentDB is a globally distributed, multi-model database service.",
  "author": {lastName: "Doe", firstName: "John"},
  "category": "Technology",
  "launchDate": ISODate("2024-06-24T10:08:20.000Z"),
  "published": true
}

Индексы одного поля

Индексы одного поля хранят сведения из одного поля в коллекции. Порядок сортировки индекса одного поля не имеет значения. _id поле остается индексировано по умолчанию.

Azure DocumentDB поддерживает создание индекса по следующим параметрам

  • Поля документа верхнего уровня.
  • Внедренный документ.
  • Поля во вложенных документах.

Следующая команда создает индекс одного поля в поле author , а следующая команда создает его в внедренном поле firstName.

use cosmicworks

db.products.createIndex({"author": 1})

// indexing embedded property
db.products.createIndex({"author.firstName": -1})

Один запрос может использовать несколько индексов одного поля, где они доступны.

Замечание

Azure DocumentDB позволяет создавать не более 64 индексов в коллекции. В зависимости от уровня можно запланировать расширение до 300 индексов по запросу.

Составные индексы

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

Следующая команда создает составной индекс в полях author и launchDate в противоположном порядке сортировки.

use cosmicworks

db.products.createIndex({"author":1, "launchDate":-1})

Order поля влияют на выборку или использование индекса. Запрос find не будет использовать созданный индекс.

use cosmicworks

db.products.find({"launchDate": {$gt: ISODate("2024-06-01T00:00:00.000Z")}})

Ограничения

  • Не более 32 полей\путей в составном индексе.

Частичные индексы

Индексы, имеющие связанный фильтр запросов, описывающий, когда нужно создать термин в индексе.

use cosmicworks

db.products.createIndex (
   { "author": 1, "launchDate": 1 },
   { partialFilterExpression: { "launchDate": { $gt: ISODate("2024-06-24T10:08:20.000Z") } } }
)

Ограничения

  • Частичные индексы не поддерживают ORDER BY или UNIQUE, если фильтр не соответствует требованиям.

Текстовые индексы

Текстовые индексы — это специальные структуры данных, которые оптимизируют текстовые запросы, что делает их более быстрыми и эффективными.

createIndex Используйте метод с параметром text для создания текстового индекса в title поле.

use cosmicworks;

db.products.createIndex({ title: "text" })

Замечание

Хотя вы можете определить только один текстовый индекс для каждой коллекции, Azure DocumentDB позволяет создавать текстовые индексы для сочетания нескольких полей, чтобы обеспечить выполнение поиска текста в разных полях в документах.

Настройка параметров текстового индекса

Текстовые индексы в Azure DocumentDB доступны с несколькими параметрами для настройки их поведения. Например, можно указать язык для анализа текста, задать весовые значения для определения приоритета определенных полей и настроить поиск без учета регистра. Ниже приведен пример создания текстового индекса с параметрами:

  • Создайте индекс для поддержки поиска в полях title и content с поддержкой английского языка. Кроме того, присвойте полю более высокий вес, чтобы определить приоритет в результатах title поиска.

    use cosmicworks
    
    db.products.createIndex(
        { title: "text", content: "text" },
        { default_language: "english", weights: { title: 10, content: 5 }, caseSensitive: false }
    )
    

Замечание

Когда клиент выполняет текстовый поисковый запрос с термином DocumentDB, оценка каждого документа в коллекции будет вычисляться на основе присутствия и частоты термина в полях "title" и "content", с более высоким значением поля "title" из-за его более высокого веса.

Выполнение поиска текста с помощью текстового индекса

После создания текстового индекса можно выполнять поиск текста с помощью оператора text в запросах. Оператор текста принимает строку поиска и сопоставляет ее с текстовым индексом, чтобы найти соответствующие документы.

  • Выполните поиск текста для фразы DocumentDB.

    use cosmicworks
    
    db.products.find(
      { $text: { $search: "DocumentDB" } }
    )
    
  • При необходимости используйте $meta оператор проекции вместе с textScore полем в запросе, чтобы просмотреть вес

    use cosmicworks
    
    db.products.find(
    { $text: { $search: "DocumentDB" } },
    { score: { $meta: "textScore" } }
    )
    

Ограничения

  • В коллекции можно определить только один текстовый индекс.
  • Операции сортировки не могут использовать упорядочение текстового индекса в MongoDB.
  • Hint() не поддерживается в сочетании с запросом с помощью выражения $text.
  • Текстовые индексы могут быть относительно большими, потребляя значительное место в хранилище по сравнению с другими типами индексов.

Индексы подстановочных символов

Индекс по одному полю индексирует все пути, расположенные под field, исключая другие поля, расположенные на том же уровне. Например, для следующего примера документа

{
 "children":
    {
     "familyName": "Merriam",
     "pets": { "details": {“name”: "Goofy", ”age”: 3} }
   } 
}

Создание индекса на { "pets.$**": 1 }, создает индекс на деталях и свойствах поддокументов, но не создает индекс на "familyName".

Ограничения

  • Подстановочные индексы не могут поддерживать уникальные индексы.
  • Индексы подстановочных символов ORDER BY не поддерживают встроенных операций, если фильтр содержит только пути, присутствующие в подстановочных символах (так как они не индексируют неопределенные элементы)
  • Составной индекс подстановочного знака может содержать только один подстановочный термин one и one или более терминов индекса. { "pets.$**": 1, “familyName”: 1 }

Геопространственные индексы

Геопространственные индексы поддерживают запросы к данным, хранящимся в виде объектов GeoJSON или устаревших пар координат. Геопространственные индексы можно использовать для повышения производительности запросов на геопространственные данные или для выполнения определенных геопространственных запросов.

Azure DocumentDB предоставляет два типа геопространственных индексов:

  • Индексы 2dsphere, поддерживающие запросы, которые интерпретируют геометрию на сфере.
  • 2d Indexes, поддерживающие запросы, которые интерпретируют геометрию на плоской поверхности.

2d-индексы

Индексы 2d поддерживаются только в старом формате пар координат для хранения геопространственных данных.

Используйте метод createIndex с параметром 2d для создания геопространственного индекса на поле location.

db.places.createIndex({ "location": "2d"});

Ограничения

  • Только one поле расположения может быть частью 2d индекса, а только one ещё одно негеопространственное поле может быть частью compound 2d индекса. db.places.createIndex({ "location": "2d", "non-geospatial-field": 1 / -1 })

индексы 2dsphere

2dsphere индексы поддерживают геопространственные запросы на земной шаре. Он может поддерживать оба объекта GeoJSON или устаревшие пары координат. 2dSphere индексы работают со стилем GeoJSON для хранения данных, если обнаружены устаревшие точки, индексы преобразуют их в точки GeoJSON.

Используйте метод createIndex с параметром 2dsphere для создания геопространственного индекса поля location.

db.places.createIndex({ "location": "2dsphere"});

2dsphere индексы позволяют создавать индексы в нескольких геопространственных и нескольких полях данных, отличных от геопространственных. db.places.createIndex({ "location": "2d", "non-geospatial-field": 1 / -1, ... "more non-geospatial-field": 1 / -1 })

Ограничения

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

    // Compound Regular & 2dsphere indexes are not supported yet
    db.collection.createIndex({a: 1, b: "2dsphere"})
    
    // Compound 2d indexes are not supported yet
    db.collection.createIndex({a: "2d", b: 1})
    
  • Многоугольники с отверстиями не работают. Вставка многоугольника с отверстием не ограничена, хотя $geoWithin запрос терпит сбой в некоторых сценариях.

    1. Если сам запрос имеет многоугольник с отверстиями

      coll.find(
        {
            "b": {
                "$geoWithin": {
                    "$geometry": {
                        "coordinates": [
                            [
                                [ 0, 0], [0, 10], [10, 10],[10,0],[0, 0]
                            ],
                            [
                                [5, 5], [8, 5], [ 8, 8], [ 5, 8], [ 5, 5]
                            ]
                        ],
                        "type": "Polygon"
                    }
                }
            }
        })
      
      // MongoServerError: $geoWithin currently doesn't support polygons with holes
      
    2. Если есть нефильтрованный документ с многоугольником с отверстиями.

      [mongos] test> coll.find()
        [
          {
            _id: ObjectId("667bf7560b4f1a5a5d71effa"),
            b: {
              type: 'Polygon',
              coordinates: [
                [ [ 0, 0 ], [ 0, 10 ], [ 10, 10 ], [ 10, 0 ], [ 0, 0 ] ],
                [ [ 5, 5 ], [ 8, 5 ], [ 8, 8 ], [ 5, 8 ], [ 5, 5 ] ]
              ]
            }
          }
        ]
      // MongoServerError: $geoWithin currently doesn't support polygons with holes
      
    3. key поле является обязательным при использовании geoNear.

       [mongos] test> coll.aggregate([{ $geoNear: { $near: { "type": "Point", coordinates: [0, 0] } } }])
      
       // MongoServerError: $geoNear requires a 'key' option as a String
      

Дальнейшие шаги