Элемент сортировки по массивам не работает в Elasticsearch при загрузке Spring с использованием API Java

У меня проблема (или нехватка знаний) при сортировке документов в asticsearch. Elasticsearch является локальным и управляется весенней загрузкой. То, что я пытаюсь сделать, это, используя Java API, искать документы и сортировать их. Документы выглядят примерно так (немного упрощенно):

{
(...)
"relatedDocuments": [{
    "_id": ObjectId("123123"),
    (...)
    "relationSet": [{
        "type": {
            "name": "Some name",
            "version": NumberLong(1)
        },
        "documentId": "123123",
        "content": {
            "numberToSearch": "U-2016-8"<---element to sort by
        }
    }]
    (...)
}]
(...)
}

Как вы можете видеть, элемент для сортировки находится в объекте, который находится в массиве, который находится в другом объекте, удерживаемом другим массивом...

Теперь я делаю некоторый запрос, который, кажется, работает нормально, но сортировка... как сортировка никогда не происходила... Java-код выглядит примерно так:

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //some bool query created
        boolQuery.must(query);
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withSort(SortBuilders.fieldSort("relatedDocuments.relationSet.content.numberToSearch").order(SortOrder.ASC).sortMode("min")).withQuery(boolQuery).build();

        return elasticsearchTemplate.queryForList(searchQuery, GenericDocumentIndex.class);

результат правильно ищется, но не сортируется вообще...

Если я изменю fieldSort на что-то более простое, например "relatedDocuments.id", то сортировка будет работать...

Что здесь не так?

РЕДАКТИРОВАТЬ
Для справки приведенные рекорды отсортированы как ниже:

U-2016-5
U-2016-6
U-2016-7
U-2016-4
U-2016-8
U-2016-9
U-2016-12
U-2016-11
U-2016-10

2 ответа

Решение

Хорошо
проблема была не в структуре запроса или документа, а в значении поля...

он был разделен дефисом, поэтому упругий поиск не содержал его как целую строку, а как отдельные токены. Решение состоит в том, чтобы установить это поле (или добавить подполе) с помощью свойства not_analyzed с индексом... В Java это можно было бы сделать, добавив аннотацию к полю, как это или подобное:

@Field(
        type = FieldType.String,
        index = FieldIndex.not_analyzed
)
relationSet seems like a nested field in your schema. 

Для сортировки по вложенным полям следует обратиться по ссылке ниже

Ссылка: https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-sorting.html

"sort": [{
        "relatedDocuments.relationSet.content.numberToSearch": {
            "nested_path": "relatedDocuments.relationSet",
            "mode": "min",
            "order": "desc",
            "ignore_unmapped": false
        }
    }],

ОБНОВИТЬ:

Вы должны явно отметить relationSet как вложено через подпружиненную загрузку

@Document(indexName = "indexName", type = "inxedType", shards = 1, replicas = 0)
public class RelatedDocuments {
@Field(type= FieldType.Nested)  // <-- mark it as nested
private List<Relation> relationSet;   
}

PS: удалить индекс и воссоздать, прежде чем продолжить

Другие вопросы по тегам