Spring Data Solr 教程: 排序

當實現一個字符查詢功能時,通常都會以搜索結果的質量高低來降序顯示 relevancy of each search result。 這也正是Solr的作法。
然而,有時也須要採用手工干預的方式來調整展現順序。其中一個場景就是在以前文中 previous part of my Spring Data Solr tutorial。 提到的」常規」檢索的實現
該文說明了如何使用 Spring Data Solr 來分類查詢結果。具體就是說明如何經過修改示例應用的查詢功能以使用id字段的值來降序展現查詢結果。
文章能夠分爲三大塊:html

  • 第一部分講解了如何在查詢語句中設置排序條件
  • 第二部分說的是使用查詢方法時如何排序查詢結果
  • 第三部分告訴咱們如何進行動態查詢結果的排序

我們繼續往下看java

定義排序條件

查詢語句中的排序是經過 Sort 類來實現的。常見的排序方式以下:git

  • 按單個字段結果排序
  • 當按多個不一樣字段的排序結果相同時按多個字段組合排序
  • 當按多個不一樣字段的排序結果不一樣時按多個字段組合排序

下來看看如何建立實現上述條件的Sort對象
首先,建立一個按單字段排序的Sort對象。假設咱們想按照Id字段的值來升序排列,實現代碼以下:github

new Sort(Sort.Direction.ASC, "id")

其次,建立知足場景二中的Sort對象。這裏假設咱們使用id 和description 爲查詢字段並將結果以降序排列。實現代碼以下:spring

new Sort(Sort.Direction.DESC, "id", "description")

最後,建立知足場景三的Sort對象。這裏假設降序排列description升序排列id 字段的查詢結果。實現代碼以下:apache

new Sort(Sort.Direction.DESC, "description").and(new Sort(Sort.Direction.ASC, "id"))

如今知道了如何建立相應的Sort對象,再來看看如何在具體狀況中的使用。api

查詢方法結果排序

當使用查詢方法時,能夠按如下步驟來排序查詢結果:dom

  1. 在方法體中加入Sort參數。用來傳遞排序設置
  2. 在服務層建立一個Sort對象,當調用查詢方法時將其做爲變量傳遞過去

下面具體看一下是如何實現的.ide

修改Repository接口

咱們能夠經過在查詢方法體中添加一個變量來控制未來查詢結果的排序狀況。下面來看看查詢方法的定義:學習

從方法名派生查詢語句

若是使用了從方法名生成查詢語句的策略,那須要在TodoDocumentRepositoryinterface的
findByTitleContainsOrDescriptionContains() 方法中添加Sort參數。源碼以下:

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);
}

命名查詢語句

若是使用命名查詢語句的策略,那須要在odoDocumentRepository 的thefindByNamedQuery() 方法中添加Sort參數。源碼以下:

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該功能不能正常工做源於 known bug.
如此,要麼使用snapshot依賴或是使用RC2版本。

@Query 註解

若是使用@Query註解模式,咱們要在theTodoDocumentRepository 接口中的 findByQueryAnnotation() 方法中添加Sort 參數。源碼以下:

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該功能不能正常工做源於 known bug。如此,要麼使用snapshot依賴或是使用RC2版本。

查詢方法

經過修改RepositoryIndexService 類中的thesearch() 方法實現修改查詢方法體

  1. 建立sortByIdDesc()方法實現以文檔的id爲關鍵字降序排列結果
  2. 經過調用 TodoDocumentRepository接口中定義的查詢方法獲取查詢結果
  3. 返回查詢結果集

再來看看search()方法的不一樣實現方式。

從方法名稱生成查詢

當咱們按照方法名稱策略經過查詢生成來構造咱們的查詢時,可使用TodoDocumentRepository接口的findByTitleContainsOrDescriptionContains() 方法得到查詢結果。
RepositoryTodoIndexService 類的相關部分源代碼大體以下:

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
}

命名查詢
當咱們用命名查詢構建咱們的查詢時,咱們能夠利用TodoDocumentRepository接口的findByNamedQuery()方法獲得查詢結果。
RepositoryTodoIndexService 相關部分的代碼以下:

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註解來構建咱們的查詢時,咱們可使用TodoDocumentRepository接口的findByQueryAnnotation()方法來獲取查詢結果。
RepositoryTodoIndexService 類的相關部分以下:

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
}

排序動態查詢的查詢結果

由於 動態查詢 是經過 在倉儲接口中添加自定義方法實現的, 因此對動態查詢的結果進行排序的步驟不會影響到咱們的實例應用中的Service層。
咱們能夠經過對咱們自定義倉儲接口的實現進行以下修改來排序動態查詢的結果集。

  1. 在TodoDocumentRepositoryImpl類中添加一個 private sortByIdDesc() 方法。這個方法返回一個Sort對象,這個對象指定查詢結果集以id降序排列。
  2. 修改TodoDocumentRepositoryImpl 的search()方法.使用Query 接口的addSort()方法來設置執行查詢的排序選項,而且將建立的Sort對象做爲參數傳遞給addSort()。

TodoDocumentRepositoryImpl 類的相關方法以下:

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 類來指定排序選項。
  • 咱們學習到能夠對query方法增長一個新的參數的查詢,來對結果進行排序。
  • 咱們學習到能夠給一個動態查詢設置排序選項,方法是使用Query接口的addSort()方法。

下一次,個人Spring Data Solr教程會描述如何對咱們的查詢結果進行分頁
P.S. 本博客文章中的樣例程序已經發布到Github (query方法動態查詢)。


原文: Spring Data Solr Tutorial: Sorting
轉載自:開源中國 - petert, lwei, 趙亮-碧海情天, GoodLoser, HTCKF

相關文章
相關標籤/搜索