#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?