好久以前就安裝了elasticsearch,一直沒用java用過,最近看了一下spring data系列的elasticsearch,這裏寫一篇心得。html
若是還沒有安裝elasticsearch,能夠 參考http://www.javashuo.com/article/p-upmsiepk-gx.html這篇文章。java
先談談原生的寫法,node
private TransportClient client; public TransportClient getClient(){ Settings setting = Settings.builder() .put("cluster.name", "elas_cluster") .put("client.transport.ignore_cluster_name", true) // .put("client.transport.nodes_sampler_interval", 5) // .put("client.transport.sniff", true) .build(); client = new PreBuiltTransportClient(setting) .addTransportAddress( new TransportAddress(new InetSocketAddress("192.168.0.2",9300)) ); return client; }
首先鏈接客戶端,這裏單節點和集羣寫法一致,若是是集羣的話也只需配置master節點,官方說法是客戶端開啓嗅探以後,會把嗅探到的節點列表把本地覆蓋掉。git
由於我是用spring data elasticsearch框架導入的數據,因此這裏就不寫index, type的建立,就展現一下搜索的寫法。 github
public void search(){ QueryBuilder queryBuilder= QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("newsTitle","首個電商俱樂部")) .must(QueryBuilders.matchQuery("newsCate","科技")); SearchResponse response= client.prepareSearch("test") .setTypes("newsArticle") .setQuery(queryBuilder).get(); SearchHits searchHits = response.getHits(); for(SearchHit searchHit : searchHits) { System.out.println(searchHit); } client.close(); }
這裏先談一下基本的搜索redis
elasticsearch 搜索請求是restful風格的,它的搜索請求都是根據 json格式的參數去搜索的。spring
通常來講 elasticsearch 的普通搜索json都是相似 { "query" : ... } 這樣的,json
首先elasticsearch 的全部搜索基本分紅兩種,一個是 過濾 ,一種是查詢 (爲了區分我這裏稱得分搜索) ,它們區別舉例說明restful
像過濾搜索判斷都是直接判斷符不符合,好比是否是這個年齡範圍的,這個字段是否是匹配的,是就返回,不是就不返回,框架
而得分搜索有一個score分數做爲返回依據,好比這個字段匹配的,給你一點分數,那個字段沒匹配,沒分數,綜合全部的分數看是否是達標了,達標了返回,不達標不返回。
相似
{ "query" : {「range」 : { ....... }} }
{ "query" : {「term」 : { ....... }} } term是精確查詢,須要徹底匹配
屬於過濾搜索
{ "query" : {「match」 : { ....... }} }
{ "query" : {「bool」 : { ....... }} }
屬於得分搜索
而像{ "query" : {「bool」 : { ....... }} } 這種是組合多個查詢的,其中........ 的內容能夠是多個must 或者should或者must_not或者filter的組合,最終計算score
如今能夠進入主題了,spring data elasticsearch的用法
先導包
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.1.2.RELEASE</version> </dependency>
接着配置yml
spring:
data: elasticsearch: repositories: enabled: true cluster-nodes: 192.168.0.2:9300 cluster-name: elas_cluster
這裏說一個bug,若是有redis你可能會拋異常,我這裏是在啓動類裏配置了這麼一行
public static void main(String[] args) throws Exception{ System.setProperty("es.set.netty.runtime.available.processors", "false"); SpringApplication.run(EsStart.class,args); }
spring-data系列的框架,用過jpa的應該都知道套路
首先配置實體註解
@Document(indexName = "test",type = "newsArticle") public class NewsArticlePO { ...... }
若是有什麼字段須要分詞器,能夠單獨在字段上配置
。。。。。。 @Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_max_word") private String newsTitle; 。。。。。。
這時候一啓動項目就會發現index,type已經自動生成了
第二步
建立repository
public interface ArticleRepository extends ElasticsearchRepository<NewsArticlePO,Long> { 。。。。。。 }
這裏有幾種作法,一個是本身利用名字規則定義新的方法,一個是用query註解建立查詢,一個是使用父類繼承的方法。
第一種方法
在 ArticleRepository中建立方法
/** * 根據標題,類別兩個字段搜索 * */ List<NewsArticlePO> findByNewsTitleAndAndNewsCate(String newsTitle,String newsCate);
具體規則參考spring data elasticsearch的官方文檔附錄
第二種方法
在 ArticleRepository中建立方法
@Query("{\"bool\": {\"must\": [{ \"match\": { \"newsTitle\": \"?0\"}},{ \"match\": { \"newsCate\": \"?1\"}}]}}")
List<NewsArticlePO> findByQuery(String newsTitle, String newsCate);
第三種方法
在service層代碼或者其餘類中注入 ArticleRepository
@Resource private ArticleRepository articleRepository;
建立方法
public Page<NewsArticlePO> searchBuild(String newsTitle, String newsCate) { QueryBuilder queryBuilder= QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("newsTitle",newsTitle)) .must(QueryBuilders.matchQuery("newsCate",newsCate)); SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(queryBuilder) .build(); return articleRepository.search(searchQuery); }
這就ok了,若是不喜歡使用repository也沒事,能夠注入ElasticsearchTemplate
@Resource private ElasticsearchTemplate elasticsearchTemplate; public List<NewsArticlePO> searchTemplate(String newsTitle, String newsCate){ QueryBuilder queryBuilder= QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("newsTitle",newsTitle)) .must(QueryBuilders.matchQuery("newsCate",newsCate)); SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(queryBuilder) .build(); return elasticsearchTemplate.queryForList(searchQuery,NewsArticlePO.class); }
甚至能夠經過elasticsearchTemplate.getClient()獲得原生的client進行操做
demo項目地址 https://github.com/1160809039/elasticsearch-demo