#elasticsearch
#elasticsearch
Вопрос:
Требование: я хочу выполнить запрос и отсортировать по date field
, которое может не существовать. Поле даты записей не существует, все должно быть включено первым, тогда записи, date field
значение которых меньше 1600230168278
, будут включены туда позже. Сначала будут упорядочены те записи, которые не существуют date field
затем date ascending
Отображение и образцы данных:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date"
},
"name": {
"type": "text"
}
}
}
}
}
PUT my_index/_doc/1
{
"date": 1546300800000
}
PUT my_index/_doc/2
{
"date": 1577836800000
}
PUT my_index/_doc/3
{
"date": 1609459200000
}
PUT my_index/_doc/4
{
"name": "Arif Mahmud Rana"
}
Мой запрос:
{
"query": {
"bool": {
"must": {
"function_score": {
"functions": [
{
"filter": {
"exists": {
"field": "date"
}
},
"weight": 0.5
}
],
"query": {
"match_all": {}
}
}
},
"filter": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"exists": {
"field": "date"
}
},
{
"range": {
"date": {
"lt": 1600230168278
}
}
}
]
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "date"
}
}
}
}
]
}
}
}
},
"sort": [
{
"_score": "desc"
},
{
"date": "asc"
}
],
"size": 100
}
Результат запроса:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : null,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.0,
"_source" : {
"name" : "Arif Mahmud Rana"
},
"sort" : [
1.0,
9223372036854775807
]
},
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5,
"_source" : {
"date" : 1546300800000
},
"sort" : [
0.5,
1546300800000
]
},
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.5,
"_source" : {
"date" : 1577836800000
},
"sort" : [
0.5,
1577836800000
]
}
]
}
}
Это отлично работает для этого простого индекса с меньшим количеством данных, но при работе с большим индексом мой эластичный узел выходит из строя.
Эластичная версия: 6.8.5
Фактический индекс: 3048140( docs.count
), 1073559( docs.deleted
), 1,3 ГБ ( store.size
) и 1,3 ГБ ( pri.store.size
)
Любая помощь или идея будут полезны TIA.
Ответ №1:
Я считаю, что пользовательская оценка во всех документах, не имеющих поля даты в большом индексе, вызывает проблему.
Вот способ, которым это можно сделать для достижения вашей цели использования, используя missing
для определения критериев сортировки для документов с отсутствующим полем сортировки.
GET test/_search
{"query":{"match_all":{}}}
PUT /test
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"age": { "type": "integer" }
}
}
}
POST test/_doc
{
"name": "shahin",
"age": 234
}
POST test/_doc
{
"name": "karim",
"age": 235
}
POST test/_doc
{
"name": "rahim"
}
POST test/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must":
{
"range": {
"age": {
"lt": 250
}
}
}
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "age"
}
}
}
}
]
}
},
"sort": [
{ "age" : {"missing" : "_first", "order": "asc"}}
],
"size": 100
}
Комментарии:
1. Шахин вхай большое спасибо, это действительно значительно улучшило производительность
Ответ №2:
Я добавил некоторую оптимизацию, которая может помочь другим. Я индексировал свой производственный индекс по этому индексу. Мне пришлось выполнять поиск / запрос, а затем перебирать эти данные и индексировать в моем производственном индексе. Вот мой производственный запрос.
GET /my_index/_search?filter_path=hits.hits._id,hits.hits._source
{
"query": {
"bool": {
"filter": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"range": {
"lastModified": {
"lte": 1600314822988
}
}
},
{
"bool": {
"must_not": {
"exists": {
"field": "lastModified"
}
}
}
}
]
}
}
}
},
"sort": [
{
"indexed": {
"order": "asc",
"missing": "_first"
}
},
{
"lastModified": {
"order": "asc",
"missing": "_first"
}
}
],
"size": 100
}
Я использовал filter
over should
, поскольку моему запросу не нужна оценка по совпадающим элементам. Также я использовал filter_path
для получения только обязательных полей. После добавления этой оптимизации мой запрос был как минимум на 4 секунды быстрее.