По умолчанию elascticsearch (ES) НЕ индексирует (отдельно) и НЕ сортирует записи по полю _id
. Значения для _id
вытаскиваются из поля _uid
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-id-field.html
Вместо этого он индексирует поле _uid
, которое и содержит в себе информацию об _id
и _type
в виде {type}#{id}
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-uid-field.html
Сортировка же по полю _uid
является некорректной в виду того, что _id
в нем является не integer
, а string
объектом.
Почитать о поле _type
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-type-field.html
- модель, объекты которой должны бать отсортированы по
id
-LogDebug
- подключаемый к ней модуль с логикой индексации, поиска и сортировки
elasticsearch
-LogDebugElasticsearchSearchable
- так как мы хотим добавить в ES custom field
sort_id
, а кастомные поля не индексируются дефолтным колбэком ES, тогда in model add callbacksafter_save
andafter_destroy
../app/models/log_dedug.rb
class LogDebug < ActiveRecord::Base
self.table_name = "log_debug"
....
### search elasticsearch
include LogDebugElasticsearchSearchable
# add object, with filds who absent in DB, to elasticsearch
after_save :es_update
after_destroy :es_update
...
# for indexing custom fields
def es_update
self.__elasticsearch__.index_document
end
end
- in including module hasing default ES callback and add field to ES, which contain
id
ininteger
format
../app/models/concerns/log_debug_elasticsearch_searchable.rb
module LogDebugElasticsearchSearchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
#include Elasticsearch::Model::Callbacks <--- хэшировать дефолтный коллбэк обязательно
...
settings index: { number_of_shards: 1 } do
mappings dynamic: 'true' do
...
# for ES sorting by id
indexes :sort_id, :index => :not_analyzed, :type => 'integer'
end
end
def as_indexed_json(options={})
attrs = {
...
# for ES sorting by id
:sort_id => self.id,
}
attrs.as_json
end
# block for search
def self.search(asc_or_desc)
...
#
__elasticsearch__.search(
{
...some query...
sort: get_order(asc_or_desc)
}
)
end
...
def self.get_order(asc_or_desc)
[{"sort_id" => {:order => asc_or_desc}}]
end
end
end
- для того, чтобы сделать index/reindex полей в ES, может быть выполнен следующий код
...
def import_log_debug_index
#
LogDebug.__elasticsearch__.create_index! force: true
LogDebug.__elasticsearch__.refresh_index!
LogDebug.import(:force=>true, index: 'some_index')
end
end