Запросы Elasticsearch к Milvus
Elasticsearch, построенный на базе Apache Lucene, является ведущей поисковой системой с открытым исходным кодом. Однако в современных приложениях искусственного интеллекта он сталкивается с такими проблемами, как высокая стоимость обновления, низкая производительность в реальном времени, неэффективное управление шардами, не облачный нативный дизайн и чрезмерные требования к ресурсам. Milvus, являясь облачной векторной базой данных, решает эти проблемы за счет разделения хранения и вычислений, эффективного индексирования для высокоразмерных данных и бесшовной интеграции с современными инфраструктурами. Она обеспечивает превосходную производительность и масштабируемость для рабочих нагрузок ИИ.
Цель этой статьи - облегчить миграцию вашей кодовой базы с Elasticsearch на Milvus, предоставив различные примеры преобразования запросов между ними.
Обзор
В Elasticsearch операции в контексте запроса генерируют оценки релевантности, а операции в контексте фильтра - нет. Аналогично, поиск в Milvus выдает оценки сходства, а его фильтроподобные запросы - нет. При переносе кодовой базы с Elasticsearch на Milvus ключевым принципом является преобразование полей, используемых в контексте запроса Elasticsearch, в векторные поля, чтобы обеспечить генерацию оценок сходства.
В таблице ниже приведены некоторые шаблоны запросов Elasticsearch и их эквиваленты в Milvus.
Запросы Elasticsearch |
Эквиваленты в Milvus |
Примечания |
|---|---|---|
Полнотекстовые запросы |
||
Полнотекстовый поиск |
Оба предоставляют схожие возможности. |
|
Запросы на уровне терминов |
||
|
Оба предоставляют одинаковый или похожий набор возможностей при использовании этих запросов Elasticsearch в контексте фильтра. |
|
|
||
Операторы сравнения, такие как |
||
Операторы сравнения типа |
||
|
||
|
||
Логические операторы типа |
Оба оператора предоставляют схожие возможности при использовании в контексте фильтра. |
|
Векторные запросы |
||
Поиск |
Milvus предоставляет более продвинутые возможности векторного поиска. |
|
Гибридный поиск |
Milvus поддерживает несколько стратегий ранжирования. |
|
Полнотекстовые запросы
В Elasticsearch полнотекстовые запросы позволяют искать в анализируемых текстовых полях, например в теле письма. Строка запроса обрабатывается с помощью того же анализатора, который был применен к полю во время индексирования.
Запрос на совпадение
В Elasticsearch запрос на совпадение возвращает документы, которые соответствуют заданному тексту, числу, дате или логическому значению. Предоставленный текст анализируется перед поиском.
Ниже приведен пример поискового запроса Elasticsearch с запросом на совпадение.
resp = client.search(
query={
"match": {
"message": {
"query": "this is a test"
}
}
},
)
Milvus предоставляет такую же возможность с помощью функции полнотекстового поиска. Вы можете преобразовать приведенный выше запрос Elasticsearch в Milvus следующим образом:
res = client.search(
collection_name="my_collection",
data=['How is the weather in Jamaica?'],
anns_field="message_sparse",
output_fields=["id", "message"]
)
В приведенном выше примере message_sparse - это разреженное векторное поле, полученное из поля VarChar с именем message. Milvus использует модель встраивания BM25 для преобразования значений в поле message в разреженные векторные вложения и сохраняет их в поле message_sparse. Получив поисковый запрос, Milvus встраивает полезную нагрузку текстового запроса, используя ту же модель BM25, выполняет поиск по разреженному вектору и возвращает поля id и message, указанные в параметре output_fields, вместе с соответствующими оценками сходства.
Чтобы использовать эту функциональность, необходимо включить анализатор для поля message и определить функцию для получения из него поля message_sparse. Подробные инструкции по включению анализатора и созданию производной функции в Milvus см. в разделе Полнотекстовый поиск.
Запросы на уровне терминов
В Elasticsearch запросы на уровне терминов используются для поиска документов на основе точных значений в структурированных данных, таких как диапазоны дат, IP-адреса, цены или идентификаторы продуктов. В этом разделе описаны возможные эквиваленты некоторых запросов уровня терминов Elasticsearch в Milvus. Все примеры в этом разделе адаптированы для работы в контексте фильтра, чтобы соответствовать возможностям Milvus.
Идентификаторы
В Elasticsearch вы можете найти документы по их идентификаторам в контексте фильтра следующим образом:
resp = client.search(
query={
"bool": {
"filter": {
"ids": {
"values": [
"1",
"4",
"100"
]
}
}
}
},
)
В Milvus вы также можете находить сущности по их идентификаторам следующим образом:
# Use the filter parameter
res = client.query(
collection_name="my_collection",
filter="id in [1, 4, 100]",
output_fields=["id", "title"]
)
# Use the ids parameter
res = client.query(
collection_name="my_collection",
ids=[1, 4, 100],
output_fields=["id", "title"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее о запросах query и get, а также о выражениях фильтрации в Milvus читайте в разделе Запросы и фильтрация.
Префиксный запрос
В Elasticsearch вы можете найти документы, содержащие определенный префикс в указанном поле в контексте фильтра следующим образом:
resp = client.search(
query={
"bool": {
"filter": {
"prefix": {
"user": {
"value": "ki"
}
}
}
}
},
)
В Milvus вы можете найти сущности, значения которых начинаются с указанного префикса, следующим образом:
res = client.query(
collection_name="my_collection",
filter='user like "ki%"',
output_fields=["id", "user"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее об операторе like в Milvus читайте в разделе Использование LIKE для поиска по шаблону.
Запрос диапазона
В Elasticsearch вы можете найти документы, содержащие термины в заданном диапазоне, следующим образом:
resp = client.search(
query={
"bool": {
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
},
)
В Milvus вы можете найти сущности, значения которых в определенном поле находятся в заданном диапазоне следующим образом:
res = client.query(
collection_name="my_collection",
filter='10 <= age <= 20',
output_fields=["id", "user", "age"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее об операторах сравнения в Milvus см. в разделе Операторы сравнения.
Запрос термина
В Elasticsearch вы можете найти документы, содержащие точный термин в указанном поле, как показано ниже:
resp = client.search(
query={
"bool": {
"filter": {
"term": {
"status": {
"value": "retired"
}
}
}
}
},
)
В Milvus вы можете найти сущности, значения которых в указанном поле в точности соответствуют указанному термину, следующим образом:
# use ==
res = client.query(
collection_name="my_collection",
filter='status=="retired"',
output_fields=["id", "user", "status"]
)
# use TEXT_MATCH
res = client.query(
collection_name="my_collection",
filter='TEXT_MATCH(status, "retired")',
output_fields=["id", "user", "status"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее об операторах сравнения в Milvus см. в разделе Операторы сравнения.
Запрос терминов
В Elasticsearch можно найти документы, содержащие один или несколько точных терминов в указанном поле, как показано ниже:
resp = client.search(
query={
"bool": {
"filter": {
"terms": {
"degree": [
"graduate",
"post-graduate"
]
}
}
}
}
)
В Milvus нет полного эквивалента этому запросу. Однако вы можете найти сущности, значения которых в указанном поле являются одним из указанных терминов, следующим образом:
# use in
res = client.query(
collection_name="my_collection",
filter='degree in ["graduate", "post-graduate"]',
output_fields=["id", "user", "degree"]
)
# use TEXT_MATCH
res = client.query(
collection_name="my_collection",
filter='TEXT_MATCH(degree, "graduate post-graduate")',
output_fields=["id", "user", "degree"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее об операторах диапазона в Milvus читайте в разделе Операторы диапазона.
Запрос с подстановочным знаком
В Elasticsearch вы можете найти документы, содержащие термины, соответствующие шаблону с подстановочным знаком, как показано ниже:
resp = client.search(
query={
"bool": {
"filter": {
"wildcard": {
"user": {
"value": "ki*y"
}
}
}
}
},
)
Milvus не поддерживает подстановочные знаки в условиях фильтрации. Однако вы можете использовать оператор like для достижения аналогичного эффекта, как показано ниже:
res = client.query(
collection_name="my_collection",
filter='user like "ki%" AND user like "%y"',
output_fields=["id", "user"]
)
Пример Elasticsearch можно найти на этой странице. Подробнее об операторах диапазона в Milvus читайте в разделе Операторы диапазона.
Булевский запрос
В Elasticsearch булевый запрос - это запрос, который подбирает документы, соответствующие булевым комбинациям других запросов.
Следующий пример адаптирован из примера в документации Elasticsearch на этой странице. Запрос возвращает пользователей с kimchy в их именах с тегом production.
resp = client.search(
query={
"bool": {
"filter": {
"term": {
"user": "kimchy"
}
},
"filter": {
"term": {
"tags": "production"
}
}
}
},
)
В Milvus вы можете сделать то же самое следующим образом:
filter =
res = client.query(
collection_name="my_collection",
filter='user like "%kimchy%" AND ARRAY_CONTAINS(tags, "production")',
output_fields=["id", "user", "age", "tags"]
)
В приведенном выше примере предполагается, что в целевой коллекции есть поле user типа VarChar и поле tags типа Array. Запрос вернет пользователей с kimchy в имени с тегом production.
Векторные запросы
Векторные запросы в Elasticsearch - это специализированные запросы, которые работают с векторными полями для эффективного выполнения семантического поиска.
Knn-запрос
Elasticsearch поддерживает как приблизительные kNN-запросы, так и точные, грубые kNN-запросы. В любом случае можно найти k ближайших векторов к вектору запроса, измеряемых метрикой сходства, следующим образом:
resp = client.search(
index="my-image-index",
size=3,
query={
"knn": {
"field": "image-vector",
"query_vector": [
-5,
9,
-12
],
"k": 10
}
},
)
Milvus, как специализированная база данных векторов, использует типы индексов для оптимизации поиска векторов. Как правило, для высокоразмерных векторных данных приоритетным является поиск ближайших соседей (ANN). Хотя грубый kNN-поиск с типом индекса FLAT дает точные результаты, он требует много времени и ресурсов. В отличие от этого, поиск ANN с использованием AUTOINDEX или других типов индексов обеспечивает баланс между скоростью и точностью, предлагая значительно более быструю и ресурсоэффективную производительность, чем kNN.
Аналогичный векторный запрос в Mlivus выглядит следующим образом:
res = client.search(
collection_name="my_collection",
anns_field="image-vector"
data=[[-5, 9, -12]],
limit=10
)
Пример Elasticsearch можно найти на этой странице. Подробнее о поиске с помощью ANN в Milvus читайте в статье Базовый поиск с помощью ANN.
Слияние реципрокных рангов
Elasticsearch предоставляет функцию Reciprocal Rank Fusion (RRF) для объединения нескольких наборов результатов с различными показателями релевантности в один ранжированный набор результатов.
Следующий пример демонстрирует объединение традиционного поиска по терминам с векторным поиском по k-nearest neighbors (kNN) для улучшения релевантности поиска:
client.search(
index="my_index",
size=10,
query={
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"term": {
"text": "shoes"
}
}
}
},
{
"knn": {
"field": "vector",
"query_vector": [1.25, 2, 3.5], # Example vector; replace with your actual query vector
"k": 50,
"num_candidates": 100
}
}
],
"rank_window_size": 50,
"rank_constant": 20
}
}
}
)
В этом примере RRF объединяет результаты двух ретриверов:
Стандартный поиск документов, содержащих термин
"shoes"в полеtext.kNN-поиск по полю
vectorс использованием предоставленного вектора запроса.
Каждый ретривер вносит до 50 лучших совпадений, которые повторно ранжируются RRF, и в итоге возвращается 10 лучших результатов.
В Milvus можно добиться аналогичного гибридного поиска, объединив поиск по нескольким векторным полям, применив стратегию ранжирования и получив топ-K результатов из объединенного списка. Milvus поддерживает стратегии RRF и взвешенного реранкинга. Более подробную информацию см. в разделе "Реранжирование".
Ниже приведен нестрогий эквивалент приведенного выше примера Elasticsearch в Milvus.
search_params_dense = {
"data": [[1.25, 2, 3.5]],
"anns_field": "vector",
"param": {
"metric_type": "IP",
"params": {"nprobe": 10},
},
"limit": 100
}
req_dense = ANNSearchRequest(**search_params_dense)
search_params_sparse = {
"data": ["shoes"],
"anns_field": "text_sparse",
"param": {
"metric_type": "BM25",
}
}
req_sparse = ANNSearchRequest(**search_params_sparse)
res = client.hybrid_search(
collection_name="my_collection",
reqs=[req_dense, req_sparse],
reranker=RRFRanker(),
limit=10
)
Этот пример демонстрирует гибридный поиск в Milvus, который сочетает в себе:
Плотный векторный поиск: Использование метрики внутреннего произведения (IP) с
nprobe, установленным на 10, для приблизительного поиска ближайших соседей (ANN) на полеvector.Поиск по разреженному вектору: Использование метрики сходства BM25 на поле
text_sparse.
Результаты этих поисков выполняются отдельно, объединяются и ранжируются с помощью ранжировщика Reciprocal Rank Fusion (RRF). Гибридный поиск возвращает 10 лучших сущностей из ранжированного списка.
В отличие от ранжирования RRF в Elasticsearch, которое объединяет результаты стандартных текстовых запросов и kNN-поиска, Milvus объединяет результаты поиска по разреженным и плотным векторам, предоставляя уникальную возможность гибридного поиска, оптимизированного для мультимодальных данных.
Обзор
В этой статье мы рассмотрели преобразование типичных запросов Elasticsearch в их эквиваленты в Milvus, включая запросы на уровне терминов, булевы запросы, полнотекстовые запросы и векторные запросы. Если у вас возникнут дополнительные вопросы по преобразованию других запросов Elasticsearch, обращайтесь к нам.