Когда мы реализуем функцию поиска по слову, мы обычно хотим отсортировать результаты поиска в порядке убывания, используя релевантность каждого результата поиска . Это также поведение по умолчанию 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; @Service public 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; @Service public 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; @Service public 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; @Repository public 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 ( методы запросов и динамические запросы ).