好久以前就安装了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