Когда мы реализуем функцию поиска по слову, мы обычно хотим отсортировать результаты поиска в порядке убывания, используя релевантность каждого результата поиска . Это также поведение по умолчанию Solr.
Однако бывают ситуации, когда имеет смысл задавать порядок сортировки вручную. Одной из таких ситуаций является реализация «обычной» функции поиска, которая обсуждалась в предыдущей части моего руководства по Spring Data Solr .
В этом блоге описывается, как мы можем сортировать результаты наших запросов с помощью Spring Data Solr. Чтобы быть более конкретным, мы должны изменить функцию поиска нашего примера приложения, чтобы отсортировать результаты поиска в порядке убывания, используя значение поля id .
Этот блог разделен на три раздела:
- В первом разделе описывается, как мы можем указать параметры сортировки, используемые в наших запросах.
 - Во втором разделе описывается, как мы можем сортировать результаты наших запросов при построении наших запросов с использованием методов запросов.
 - Третий раздел учит нас сортировать результаты динамических запросов.
 
Давайте начнем.
Примечание. Эти посты в блоге предоставляют дополнительную информацию, которая помогает нам понять концепции, описанные в этом посте:
- Запуск Solr с Maven
 - Руководство по Spring Data Solr: введение в Solr
 - Руководство по Spring Data Solr: настройка
 - Spring Data Solr Учебник CRUD (почти)
 - Учебник по Spring Data Solr: добавление пользовательских методов в один репозиторий
 - Учебник по Spring Data Solr: динамические запросы
 
Указание параметров сортировки запроса
Параметры сортировки запроса указываются с помощью класса Sort . Типичные требования для сортировки результатов запроса приведены в следующем:
- Сортируйте результаты запроса, используя значение одного поля.
 - Сортируйте результаты запроса, используя значения нескольких полей, если порядок сортировки разных полей одинаков.
 - Сортируйте результаты запроса, используя значения нескольких полей, если порядок сортировки разных полей не одинаков.
 
Давайте посмотрим, как мы можем создать объект Sort, который удовлетворяет заданным требованиям.
Во-первых, мы должны создать объект Sort, который указывает, что результаты запроса сортируются с использованием одного поля. Предположим, что мы хотим отсортировать результаты запроса в порядке возрастания, используя поле id . Мы можем создать объект Sort , используя следующий код:
| 
 1 
 | 
new Sort(Sort.Direction.ASC, "id") | 
Во-вторых, мы должны создать объект Sort, в котором говорится, что результаты запроса сортируются с использованием значений нескольких полей, когда порядок сортировки разных полей одинаков. Предположим, что мы должны отсортировать результаты запроса в порядке убывания, используя поля id и description . Мы можем создать объект Sort , используя следующий код:
| 
 1 
 | 
new Sort(Sort.Direction.DESC, "id", "description") | 
В-третьих, мы хотим отсортировать результаты запроса, используя значения нескольких полей, когда порядок сортировки разных полей не одинаков. Предположим, что мы хотим отсортировать результаты запроса в порядке убывания, используя поле описания, и в порядке возрастания, используя поле id . Мы можем создать объект Sort , используя следующий код:
| 
 1 
 | 
new Sort(Sort.Direction.DESC, "description").and(new Sort(Sort.Direction.ASC, "id")) | 
Теперь мы знаем, как мы можем создавать новые объекты сортировки . Давайте двигаться дальше и применять эту теорию на практике.
Сортировка результатов запроса методов запроса
Когда мы строим наши запросы, используя методы запросов, мы можем отсортировать результаты запроса, выполнив следующие действия:
- Добавьте новый параметр сортировки в метод запроса. Этот параметр метода указывает используемые параметры сортировки.
 - Создайте новый объект Sort на уровне сервиса и передайте его в качестве параметра метода при вызове метода запроса.
 
Давайте двигаться дальше и узнаем, как это делается.
Модификация интерфейса репозитория
Мы можем отсортировать результаты нашего запроса, добавив новый параметр Sort в наш метод запроса. Этот параметр метода указывает параметры сортировки выполненного запроса. Давайте продолжим и посмотрим на объявления наших методов запросов.
Генерация запроса из имени метода
Когда выполненный запрос создается с использованием генерации запроса из стратегии с именем метода, нам необходимо добавить параметр Sort в метод findByTitleContainsOrDescriptionContains () интерфейса TodoDocumentRepository . Исходный код нашего интерфейса репозитория выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
 | 
import org.springframework.data.domain.Sort;import org.springframework.data.solr.repository.Query;import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends PartialUpdateRepository, SolrCrudRepository<TodoDocument, String> {    public List<TodoDocument> findByTitleContainsOrDescriptionContains(String title, String description, Sort sort);} | 
Именованные Запросы
Когда выполненный запрос создается с использованием именованных запросов, мы должны добавить параметр Sort в метод findByNamedQuery () интерфейса TodoDocumentRepository . Исходный код нашего интерфейса репозитория выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
 | 
import org.springframework.data.domain.Sort;import org.springframework.data.solr.repository.Query;import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends PartialUpdateRepository, SolrCrudRepository<TodoDocument, String> {    @Query(name = "TodoDocument.findByNamedQuery")    public List<TodoDocument> findByNamedQuery(String searchTerm, Sort sort);} | 
Примечание. Этот подход не работает, если мы используем Spring Data Solr RC1 из-за известной ошибки . Мы должны либо использовать зависимость снимка сборки, либо дождаться выпуска RC2.
Аннотация @Query
Когда выполненный запрос создается с использованием аннотации @Query , мы должны добавить параметр Sort в метод findByQueryAnnotation () интерфейса TodoDocumentRepository . Исходный код нашего интерфейса репозитория выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
 | 
import org.springframework.data.domain.Sort;import org.springframework.data.solr.repository.Query;import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends PartialUpdateRepository, SolrCrudRepository<TodoDocument, String> {    @Query("title:*?0* OR description:*?0*")    public List<TodoDocument> findByQueryAnnotation(String searchTerm, Sort sort);} | 
Примечание. Этот подход не работает, если мы используем Spring Data Solr RC1 из-за известной ошибки . Мы должны либо использовать зависимость снимка сборки, либо дождаться выпуска RC2.
Использование метода запроса
Мы можем использовать модифицированный метод запроса, внеся следующие изменения в метод search () класса RepositoryIndexService :
- Создайте закрытый метод sortByIdDesc (), который указывает, что результаты запроса сортируются в порядке убывания с использованием идентификатора документа.
 - Получите отсортированные результаты запроса, вызвав метод запроса, объявленный в интерфейсе TodoDocumentRepository .
 - Вернуть результаты запроса.
 
Давайте продолжим и посмотрим на различные реализации метода search () .
Генерация запроса из имени метода
Когда мы строим наши запросы, используя генерацию запросов из стратегии имени метода, мы можем получить результаты запроса, используя метод findByTitleContainsOrDescriptionContains () интерфейса TodoDocumentRepository .
Исходный код соответствующей части класса RepositoryTodoIndexService выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
import org.springframework.data.domain.Sort;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class RepositoryTodoIndexService implements TodoIndexService {    @Resource    private TodoDocumentRepository repository;    @Override    public List<TodoDocument> search(String searchTerm) {        return repository.findByTitleContainsOrDescriptionContains(searchTerm, searchTerm, sortByIdDesc());    }    private Sort sortByIdDesc() {        return new Sort(Sort.Direction.DESC, "id");    }        //Other methods are omitted} | 
Именованные Запросы
Когда мы строим наши запросы, используя именованные запросы, мы можем получить результаты запроса, используя метод findByNamedQuery () интерфейса TodoDocumentRepository .
Соответствующая часть RepositoryTodoIndexService выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
import org.springframework.data.domain.Sort;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class RepositoryTodoIndexService implements TodoIndexService {    @Resource    private TodoDocumentRepository repository;    @Override    public List<TodoDocument> search(String searchTerm) {        return repository.findByNamedQuery(searchTerm, sortByIdDesc());    }    private Sort sortByIdDesc() {        return new Sort(Sort.Direction.DESC, "id");    }        //Other methods are omitted} | 
Аннотация @Query
Когда мы создаем наши запросы с помощью аннотации @Query , мы можем получить результаты запроса с помощью метода findByQueryAnnotation () интерфейса TodoDocumentRepository .
Соответствующая часть класса RepositoryTodoIndexService выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
 | 
import org.springframework.data.domain.Sort;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class RepositoryTodoIndexService implements TodoIndexService {    @Resource    private TodoDocumentRepository repository;    @Override    public List<TodoDocument> search(String searchTerm) {        return repository.findByQueryAnnotation(searchTerm, sortByIdDesc());    }    private Sort sortByIdDesc() {        return new Sort(Sort.Direction.DESC, "id");    }        //Other methods are omitted} | 
Сортировка результатов запросов динамических запросов
Поскольку динамические запросы создаются путем добавления пользовательского метода к интерфейсу репозитория , шаги, необходимые для сортировки результатов запроса динамического запроса, не влияют на уровень обслуживания нашего примера приложения.
Мы можем отсортировать результаты динамических запросов, внеся следующие изменения в реализацию нашего пользовательского интерфейса репозитория:
- Добавьте приватный метод sortByIdDesc () в класс TodoDocumentRepositoryImpl . Этот метод возвращает объект Sort, который указывает, что результаты запроса сортируются в порядке убывания с использованием идентификатора документа.
 - Измените метод search () класса TodoDocumentRepositoryImpl . Установите параметры сортировки для выполненного запроса, используя метод addSort () интерфейса Query, и передайте созданный объект Sort в качестве параметра метода.
 
Соответствующая часть класса TodoDocumentRepositoryImpl выглядит следующим образом:
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
 | 
import org.springframework.data.domain.Page;import org.springframework.data.domain.Sort;import org.springframework.data.solr.core.SolrTemplate;import org.springframework.data.solr.core.query.Criteria;import org.springframework.data.solr.core.query.SimpleQuery;import org.springframework.stereotype.Repository;import javax.annotation.Resource;import java.util.List;@Repositorypublic class TodoDocumentRepositoryImpl implements CustomTodoDocumentRepository {    @Resource    private SolrTemplate solrTemplate;    @Override    public List<TodoDocument> search(String searchTerm) {        String[] words = searchTerm.split(" ");        Criteria conditions = createSearchConditions(words);        SimpleQuery search = new SimpleQuery(conditions);                //SET SORT OPTIONS        search.addSort(sortByIdDesc());        Page results = solrTemplate.queryForPage(search, TodoDocument.class);        return results.getContent();    }    private Criteria createSearchConditions(String[] words) {        Criteria conditions = null;        for (String word: words) {            if (conditions == null) {                conditions = new Criteria("id").contains(word)                        .or(new Criteria("description").contains(word));            }            else {                conditions = conditions.or(new Criteria("id").contains(word))                        .or(new Criteria("description").contains(word));            }        }        return conditions;    }    private Sort sortByIdDesc() {        return new Sort(Sort.Direction.DESC, "id");    }    //Other methods are omitted} | 
Резюме
Теперь мы узнали, как сортировать результаты запросов с помощью Spring Data Solr. Этот урок научил нас трем вещам:
- Мы знаем, что можем указать используемые параметры сортировки с помощью класса Sort .
 - Мы узнали, что можем отсортировать результат запроса методов запроса, добавив новый параметр метода в метод запроса.
 - Мы узнали, что мы можем установить параметры сортировки для динамического запроса, используя метод addSort () интерфейса Query .
 
Следующая часть моего учебника Spring Data Solr описывает, как мы можем разбить на страницы результаты наших запросов .
PS Примеры приложений этого блога доступны на Github ( методы запросов и динамические запросы ).