Как я могу проиндексировать эту таблицу MongoDB для поиска?

#mongodb #indexing

#mongodb #индексирование

Вопрос:

У меня есть коллекция «клиентов», которые имеют подобную структуру данных, и мне нужно выполнить поиск на основе имени, фамилии или DOB на корневом уровне или в AlternateClientData записях:

 {
    "_id" : GUID,
    "FirstName" : "string",
    "LastName" : "string",
    "DateOfBirth" : "YYYY-MM-dd",
    "AlternateClientData" : [ 
        {
            "AccountId" : GUID,
            "FirstName" : "string",
            "LastName" : "string",
            "DateOfBirth" : "string",
        }, 
    ]
}
  

Я использую драйвер C # Mongo, и поисковый запрос выглядит примерно так:

 "filter": {
    "AlternateClientData": {
      "$elemMatch": {
        "AccountId": {
          "$ne": null,
          "$in": [ /* one or many account IDs */]
        }
      }
    },
    "$or": [
      {
        "FirstName": {
          "$regex": "^FName",
          "$options": "i"
        }
      },
      {
        "AlternateClientData": {
          "$elemMatch": {
            "FirstName": {
              "$regex": "^FName",
              "$options": "i"
            }
          }
        }
      },
      {
        "LastName": {
          "$regex": "^LName",
          "$options": "i"
        }
      },
      {
        "AlternateClientData": {
          "$elemMatch": {
            "LastName": {
            "$regex": "^LName",
              "$options": "i"
            }
          }
        }
      },
      {
        "DateOfBirth": "1970-01-01"
      },
      {
        "AlternateClientData": {
          "$elemMatch": {
            "DateOfBirth": "1970-01-01"
          }
        }
      }
    ]
  }
  

Я пытался добавить подобный индекс, но mongo его не использует:

 {
    "FirstName" : NumberLong(1),
    "LastName" : NumberLong(1),
    "DateOfBirth" : NumberLong(1),
    "AlternateClientData.FirstName" : NumberLong(1),
    "AlternateClientData.LastName" : NumberLong(1),
    "AlternateClientData.DateOfBirth" : NumberLong(1),
    "AlternateClientData.AccountId" : NumberLong(1)
}
  

Боковое примечание: я спорил с власть имущими о том, что нам нужно потратить время на создание надлежащей службы поиска, используя что-то вроде Elastic Search, но на данный момент это просто не приоритет, поэтому я пока застрял с Mongo. Единственное, что осталось сделать на данный момент, это создать отдельную коллекцию для поиска и сгладить индексировать доступные для поиска данные?

Ответ №1:

Существует множество способов создания индекса. Одним из них вы можете определить индексы на уровне данных (при создании модели), например ;

 @Indexed(sparse = true, 
         unique = false, 
         background = true,
         direction = IndexDirection.ASCENDING, 
         name = "MyIndex",
         expireAfterSeconds = 12000,
         useGeneratedName = false)
@Field("widgetName")
 private String lastname;
  

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

 db.products.createIndex( { "FirstName": 1, "LastName": 1, "DateOfBirth": 1, "AlternateClientData.FirstName": 1 , "AlternateClientData.LastName": 1 , "AlternateClientData.DateOfBirth": 1 , "AlternateClientData.AccountId": 1 } )
  

если есть какие-либо проблемы с индексами, пожалуйста, ознакомьтесь с официальной документацией ;
https://docs.mongodb.com/manual/indexes /

Комментарии:

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

2. Для текстового индекса все по-другому. Вы можете использовать только один атрибут в коллекции для этого типа индекса. $ regex работает для всех индексов.

3. спасибо за разъяснение, я, вероятно, ошибся с операциями запроса $ text

4. Спасибо за ответ. Приведенный вами пример индекса совпадает с тем, который я привел, который Mongo по какой-то причине не использует. Есть идеи, почему он не будет использовать этот индекс? Может быть, это потому, что запрос не всегда содержит имя и фамилию? Иногда это одно или другое.

5. что находится внутри вашего $ match?