Spring Boot 中使用 SolrCloud

搜雲庫技術團隊發表於2017-10-18

Lucene是一個Java語言編寫的利用倒排原理實現的文字檢索類庫;

Solr是以Lucene為基礎實現的文字檢索應用服務。Solr部署方式有單機方式、多機Master-Slaver方式、Cloud方式。

SolrCloud是基於Solr和Zookeeper的分散式搜尋方案。當索引越來越大,一個單一的系統無法滿足磁碟需求,查詢速度緩慢,此時就需要分散式索引。在分散式索引中,原來的大索引,將會分成多個小索引,solr可以將這些小索引返回的結果合併,然後返回給客戶端。

準備

環境安裝

CentOs7.3 搭建 SolrCloud 叢集服務

測試用例

Github 程式碼

程式碼我已放到 Github ,匯入spring-boot-solr-cloud 專案

github github.com/souyunku/sp…

新增依賴

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-jpa</artifactId>
</dependency>
複製程式碼

啟用 Solr

@Configuration
@EnableSolrRepositories(basePackages = {"io.ymq.solr"}, multicoreSupport = true)
public class SolrConfig {

    @Value("${spring.data.solr.zk-host}")
    private String zkHost;

    @Bean
    public CloudSolrClient solrClient() {
        return new CloudSolrClient(zkHost);
    }
	
}
複製程式碼

對映的實體類

@SolrDocument(solrCoreName = "test_collection")
public class Ymq implements Serializable {

    @Id
    @Field
    private String id;

    @Field
    private String ymqTitle;

    @Field
    private String ymqUrl;

    @Field
    private String ymqContent;


  get 。。。

  set 。。。
}
複製程式碼

繼承 SolrCrudRepository

public interface YmqRepository extends SolrCrudRepository<Ymq, String> {

    /**
     * 通過標題查詢
     *
     * @param ymqTitle
     * @return
     */
    @Query(" ymqTitle:*?0* ")
    public List<Ymq> findByQueryAnnotation(String ymqTitle);
}
複製程式碼

CloudSolrClient 工具類

package io.ymq.solr.utils;

import io.ymq.solr.pagehelper.PageInfo;
import io.ymq.solr.pagehelper.PageInfoFacet;
import io.ymq.solr.pagehelper.RowBounds;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;

import org.apache.solr.client.solrj.response.QueryResponse;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * 描述: CloudSolrClient 工具類
 *
 * @author yanpenglei
 * @create 2017-10-19 10:56
 **/
public interface BaseSolr {

    /**
     * 新增資料
     *
     * @param defaultCollection solr 庫
     * @param bean              物件
     * @throws IOException
     * @throws SolrServerException
     */
    public void add(String defaultCollection, Object bean) throws IOException, SolrServerException;

    /**
     * 新增一組資料
     *
     * @param defaultCollection solr 庫
     * @param beans             list集合資料新增
     * @throws IOException
     * @throws SolrServerException
     */
    public void adds(String defaultCollection, Collection<?> beans) throws IOException, SolrServerException;

    /**
     * 根據多個id刪除資料
     *
     * @param defaultCollection
     * @param ids
     * @throws IOException
     * @throws SolrServerException
     */
    public void deleteByIds(String defaultCollection, List<String> ids) throws IOException, SolrServerException;

    /**
     * 根據ID刪除資料
     *
     * @param defaultCollection solr 庫
     * @param id                要刪除的文件的id
     * @throws IOException
     * @throws SolrServerException
     */
    public void deleteById(String defaultCollection, String id) throws IOException, SolrServerException;

    /**
     * 根據指定索引(欄位)模糊刪除資料
     *
     * @param defaultCollection solr 庫
     * @param field
     * @param fieldValue
     * @throws IOException
     * @throws SolrServerException
     */
    public void deleteByField(String defaultCollection, String field, String fieldValue) throws IOException, SolrServerException;

    /**
     * 查詢資料
     *
     * @param defaultCollection solr 庫
     * @param clazz             物件Po
     * @param query             查詢條件
     * @param <T>               返回查詢集合
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    public <T> List<T> query(String defaultCollection, Class<T> clazz, SolrQuery query) throws IOException, SolrServerException;

    /**
     * 查詢
     *
     * @param defaultCollection solr 庫
     * @param query             查詢條件
     * @return 返回response物件
     * @throws IOException
     * @throws SolrServerException
     */
    public QueryResponse query(String defaultCollection, SolrQuery query) throws IOException, SolrServerException;

    /**
     * @param defaultCollection solr 庫
     * @param clazz             查詢的資料對應的物件
     * @param query             查詢條件
     * @param rowBounds         分頁引數
     * @param <T>
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    public <T> PageInfo query(String defaultCollection, Class<T> clazz, SolrQuery query, RowBounds rowBounds) throws IOException, SolrServerException;

    /**
     * 查詢資料
     *
     * @param defaultCollection solr 庫
     * @param query             查詢條件
     * @param rowBounds         分頁
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    public PageInfo query(String defaultCollection, SolrQuery query, RowBounds rowBounds) throws IOException, SolrServerException;

    /**
     * solrj的facet結果集查詢
     *
     * @param defaultCollection solr 庫
     * @param query             查詢條件
     * @param rowBounds         分頁數
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    public PageInfoFacet queryFacet(String defaultCollection, SolrQuery query, RowBounds rowBounds) throws IOException, SolrServerException;
}
複製程式碼

引數配置

application.properties

#SolrCloud zookeeper
spring.data.solr.zk-host=node1:2181,node2:2181,node3:2181
複製程式碼

單元測試

package io.ymq.solr.test;

import com.alibaba.fastjson.JSONObject;
import io.ymq.solr.YmqRepository;
import io.ymq.solr.pagehelper.PageInfo;
import io.ymq.solr.pagehelper.RowBounds;
import io.ymq.solr.po.Ymq;
import io.ymq.solr.run.Startup;
import io.ymq.solr.utils.BaseSolr;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;

import org.apache.solr.client.solrj.response.QueryResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.util.List;


/**
 * 描述: 測試 solr cloud
 *
 * @author yanpenglei
 * @create 2017-10-17 19:00
 **/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Startup.class)
public class BaseTest {

    @Autowired
    private YmqRepository ymqRepository;

    @Autowired
    private CloudSolrClient cloudSolrClient;

    @Autowired
    private BaseSolr baseSolr;

    /**
     * 使用 ymqRepository 方式新增
     *
     * @throws Exception
     */
    @Test
    public void testAddYmqRepository() {

        Ymq ymq1 = new Ymq();
        ymq1.setId("1");
        ymq1.setYmqTitle("penglei");
        ymq1.setYmqUrl("www_ymq_io");
        ymq1.setYmqContent("ymqContent");

        Ymq ymq2 = new Ymq();
        ymq2.setId("2");//
        ymq2.setYmqTitle("penglei");
        ymq2.setYmqUrl("www_ymq_io");
        ymq2.setYmqContent("ymqContent");

        ymqRepository.save(ymq1);
        ymqRepository.save(ymq2);
    }


    /**
     * 使用 cloudSolrClient 方式新增
     *
     * @throws Exception
     */
    @Test
    public void testAddCloudSolrClient() throws IOException, SolrServerException {

        Ymq ymq = new Ymq();
        ymq.setId("3");
        ymq.setYmqTitle("penglei");
        ymq.setYmqUrl("www_ymq_io");
        ymq.setYmqContent("ymqContent");

        cloudSolrClient.setDefaultCollection("test_collection");
        cloudSolrClient.connect();

        cloudSolrClient.addBean(ymq);
        cloudSolrClient.commit();
    }

    /**
     * 刪除資料
     */
    @Test
    public void testDelete() {

        Ymq ymq = new Ymq();
        ymq.setId("4");
        ymq.setYmqTitle("delete_penglei");
        ymq.setYmqUrl("www_ymq_io");
        ymq.setYmqContent("ymqContent");

        // 新增一條測試資料,用於刪除的測試資料
        ymqRepository.save(ymq);

        // 通過標題查詢資料ID
        List<Ymq> list = ymqRepository.findByQueryAnnotation("delete_penglei");

        for (Ymq item : list) {

            System.out.println("查詢響應 :" + JSONObject.toJSONString(item));

            //通過主鍵 ID 刪除
            ymqRepository.delete(item.getId());
        }

    }

    /**
     * data JPA 方式查詢
     *
     * @throws Exception
     */
    @Test
    public void testYmqRepositorySearch() throws Exception {

        List<Ymq> list = ymqRepository.findByQueryAnnotation("penglei");

        for (Ymq item : list) {
            System.out.println(" data JPA 方式查詢響應 :" + JSONObject.toJSONString(item));
        }
    }

    /**
     * SolrQuery 語法查詢
     *
     * @throws Exception
     */
    @Test
    public void testYmqSolrQuery() throws Exception {

        SolrQuery query = new SolrQuery();

        String ymqTitle = "penglei";

        query.setQuery(" ymqTitle:*" + ymqTitle + "* ");

        cloudSolrClient.setDefaultCollection("test_collection");
        cloudSolrClient.connect();
        QueryResponse response = cloudSolrClient.query(query);

        List<Ymq> list = response.getBeans(Ymq.class);

        for (Ymq item : list) {
            System.out.println("SolrQuery 語法查詢響應 :" + JSONObject.toJSONString(item));
        }
    }

    /**
     * 使用 baseSolr 工具類 查詢
     *
     * @throws Exception
     */
    @Test
    public void testBaseSolrQuery() throws Exception {

        SolrQuery query = new SolrQuery();

        String ymqTitle = "penglei";
        String defaultCollection = "test_collection";

        query.setQuery(" ymqTitle:*" + ymqTitle + "* ");

        List<Ymq> list = baseSolr.query(defaultCollection, Ymq.class, query);

        for (Ymq item : list) {
            System.out.println("baseSolr 工具類  查詢響應 :" + JSONObject.toJSONString(item));
        }
    }

    /**
     * 使用 baseSolr 工具類 分頁 查詢
     *
     * @throws Exception
     */
    @Test
    public void testBaseSolrPageInfoQuery() throws Exception {

        SolrQuery query = new SolrQuery();

        String ymqTitle = "penglei";
        String defaultCollection = "test_collection";

        query.setQuery(" ymqTitle:*" + ymqTitle + "* ");

        PageInfo pageInfo = baseSolr.query(defaultCollection, Ymq.class, query,new RowBounds(0,2));

        System.out.println("使用 baseSolr 工具類 分頁 查詢響應 :" + JSONObject.toJSONString(pageInfo));
    }
}

複製程式碼

一些查詢,響應

 data JPA 方式查詢響應 :{"id":"1","ymqContent":"ymqContent","ymqTitle":"penglei","ymqUrl":"www_ymq_io"}
 data JPA 方式查詢響應 :{"id":"2","ymqContent":"ymqContent","ymqTitle":"penglei","ymqUrl":"www_ymq_io"}
 data JPA 方式查詢響應 :{"id":"3","ymqContent":"ymqContent","ymqTitle":"penglei","ymqUrl":"www_ymq_io"}
複製程式碼

程式碼我已放到 Github ,匯入spring-boot-solr-cloud 專案

github github.com/souyunku/sp…

Contact

  • 作者:鵬磊
  • 出處:www.ymq.io
  • Email:admin@souyunku.com
  • 版權歸作者所有,轉載請註明出處
  • Wechat:關注公眾號,搜雲庫,專注於開發技術的研究與知識分享

關注公眾號-搜雲庫
搜雲庫

相關文章