elastic search java api入门

阅读更多

 

 

参考资料:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/index.html

注:es版本为2.4.0

 

1.下载安装:

下载地址:https://www.elastic.co/downloads/elasticsearch

下载之后解压,运行 bin/elasticsearch 即可

 

2.maven依赖:

    org.elasticsearch
    elasticsearch
    2.4 . 0
   com.alibaba
   fastjson
   1.2 . 8

 

3.具体的demo:

package  com.tch.test.elasticsearch.test;
import  java.net.InetAddress;
import  java.net.UnknownHostException;
import  java.util.ArrayList;
import  java.util.Arrays;
import  java.util.Date;
import  java.util.List;
import  java.util.concurrent.ExecutionException;
import  java.util.concurrent.TimeUnit;
import  org.apache.commons.collections4.CollectionUtils;
import  org.apache.commons.lang3.StringUtils;
import  org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import  org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import  org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import  org.elasticsearch.action.delete.DeleteResponse;
import  org.elasticsearch.action.get.GetResponse;
import  org.elasticsearch.action.get.MultiGetItemResponse;
import  org.elasticsearch.action.get.MultiGetResponse;
import  org.elasticsearch.action.index.IndexResponse;
import  org.elasticsearch.action.search.SearchResponse;
import  org.elasticsearch.action.update.UpdateRequest;
import  org.elasticsearch.action.update.UpdateResponse;
import  org.elasticsearch.client.transport.TransportClient;
import  org.elasticsearch.common.transport.InetSocketTransportAddress;
import  org.elasticsearch.common.xcontent.XContentBuilder;
import  org.elasticsearch.common.xcontent.XContentFactory;
import  org.elasticsearch.index.query.BoolQueryBuilder;
import  org.elasticsearch.index.query.QueryBuilders;
import  org.elasticsearch.search.SearchHit;
import  org.elasticsearch.search.sort.SortOrder;
import  com.alibaba.fastjson.JSON;
public  class  ElasticSearchTest {
   public  static  final  String INDEX =  "test" ;
   public  static  final  String TYPE =  "organization" ;
   public  static  TransportClient buildClient()  throws  UnknownHostException {
     return  TransportClient.builder().build()
         .addTransportAddress( new  InetSocketTransportAddress(InetAddress.getByName( "localhost" ),  9300 ));
   }
   public  static  void  closeClient(TransportClient client) {
     if (client !=  null ) {
       client.close();
     }
   }
   /**
    * 创建mapping(类似数据库的表结构)
    *
    * @param client
    *            es client
    * @param index
    *            索引名字
    * @param type
    *            索引下type的名字
    * @throws Exception
    */
   public  static  void  createOrgMapping(TransportClient client)  throws  Exception {
     IndicesExistsResponse res = client.admin().indices().prepareExists(INDEX).execute().actionGet();
     if  (res.isExists()) {
       DeleteIndexRequestBuilder delIdx = client.admin().indices().prepareDelete(INDEX);
       delIdx.execute().actionGet();
     }
     CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(INDEX);
     final  XContentBuilder organizationBuilder = XContentFactory.jsonBuilder()
         .startObject()
         .startObject(TYPE)
         .startObject( "properties" )
         .startObject( "id" )
         .field( "type" "long" )
         .endObject()
         .startObject( "name" )
         .field( "type" "string" )
         .endObject()
         .startObject( "type" )
         .field( "type" "integer" )
         .endObject()
         .startObject( "industrialModeCodes" )
         .field( "type" "integer" )
         .endObject()
         .startObject( "updatedAt" )
         .field( "type" "date" )
         .endObject()
         .endObject()
         .endObject()
         .endObject();
     createIndexRequestBuilder.addMapping(TYPE, organizationBuilder);
     // MAPPING DONE
     createIndexRequestBuilder.execute().actionGet();
   }
   /**
    * 往索引中添加数据
    *
    * @param client
    */
   public  static  void  index(TransportClient client, ESOrganization organization) {
     IndexResponse response = client.prepareIndex(INDEX, TYPE, String.valueOf(organization.getId()))
         .setSource(JSON.toJSONString(organization)).get();
     System.out.println(response.getId());
   }
   public  static  void  getById(TransportClient client, String id) {
     GetResponse response = client.prepareGet(INDEX, TYPE, id).get();
     System.out.println(response.getSourceAsString());
   }
   public  static  void  deleteById(TransportClient client, String id) {
     DeleteResponse response = client.prepareDelete(INDEX, TYPE, id).get();
     System.out.println(response);
   }
   public  static  void  update(TransportClient client, ESOrganization organization)
       throws  InterruptedException, ExecutionException {
     UpdateRequest updateRequest =  new  UpdateRequest(INDEX, TYPE, String.valueOf(organization.getId()))
         .doc(JSON.toJSONString(organization));
     UpdateResponse response = client.update(updateRequest).get();
     System.out.println(response);
   }
   public  static  void  multiGet(TransportClient client, String... ids) {
     MultiGetResponse multiGetItemResponses = client.prepareMultiGet().add(INDEX, TYPE, ids).get();
     for  (MultiGetItemResponse itemResponse : multiGetItemResponses) {
       GetResponse response = itemResponse.getResponse();
       if  (response.isExists()) {
         String json = response.getSourceAsString();
         System.out.println(json);
       }
     }
   }
   /**
    * 复杂一点的搜索
    * @param client
    * @param searchReq
    */
   public  static  void  search(TransportClient client, OrgSearchReq searchReq) {
     BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();
     if  (searchReq.getKeyword() !=  null  && searchReq.getKeyword().length >  0 ) {
       BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
       for  (String keyword : searchReq.getKeyword()) {
         queryBuilder.should(QueryBuilders.matchQuery( "name" , keyword));
       }
       orgQueryBuilder.must(queryBuilder);
     }
     if  (!CollectionUtils.isEmpty(searchReq.getTypes())) {
       BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
       for  (Integer type : searchReq.getTypes()) {
         queryBuilder.should(QueryBuilders.matchQuery( "type" , type));
       }
       orgQueryBuilder.must(queryBuilder);
     }
     if  (!CollectionUtils.isEmpty(searchReq.getIndustrialModeCodes())) {
         BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
         for  (Integer industrialMode : searchReq.getIndustrialModeCodes()) {
           queryBuilder.should(QueryBuilders.matchQuery( "industrialModeCodes" , industrialMode));
         }
         orgQueryBuilder.must(queryBuilder);
       }
     if  (searchReq.getUpdatedAt() !=  null  && searchReq.getUpdatedAt().length >  0 ) {
         if  (searchReq.getUpdatedAt()[ 0 ] !=  null ) {
           orgQueryBuilder.must(QueryBuilders.rangeQuery( "updatedAt" ).from(searchReq.getUpdatedAt()[ 0 ]));
         }
         if  (searchReq.getUpdatedAt().length ==  2  && searchReq.getUpdatedAt()[ 1 ] !=  null ) {
           orgQueryBuilder.must(QueryBuilders.rangeQuery( "updatedAt" ).to(searchReq.getUpdatedAt()[ 1 ]));
         }
       }
     if  (StringUtils.isEmpty(searchReq.getSortField())) {
       searchReq.setSortField( "updatedAt" );
     }
     System.out.println( "orgQueryBuilder: "  +orgQueryBuilder);
     SearchResponse searchResponse = client.prepareSearch(INDEX).setTypes(TYPE)
         .setQuery(orgQueryBuilder)
         .addSort(searchReq.getSortField(), getSortOrder(searchReq.getSortType()))
         .setFrom(searchReq.getOffset())
         .setSize(searchReq.getSize())
         .execute()
         .actionGet();
     List orgs =  new  ArrayList<>();
     for  (SearchHit hit : searchResponse.getHits()) {
       ESOrganization org = JSON.parseObject(hit.getSourceAsString(), ESOrganization. class );
       orgs.add(org);
     }
     System.out.println(JSON.toJSONString(orgs,  true ));
   }
   private  static  SortOrder getSortOrder(String str) {
       if  (StringUtils.isEmpty(str)) {
         return  SortOrder.ASC;
       }
       for  (SortOrder sortOrder : SortOrder.values()) {
         if  (sortOrder.name().equalsIgnoreCase(str)) {
           return  sortOrder;
         }
       }
       return  SortOrder.ASC;
     }
   private  static  ESOrganization getUpdateOrg() {
     ESOrganization organization =  new  ESOrganization();
     organization.setId(1l);
     organization.setType( 1111111111 );
     return  organization;
   }
   public  static  void  addIndex(TransportClient client) {
     String[] orgNames = {
         "小米科技有限责任公司" ,
         "乐视网信息技术(北京)股份有限公司" ,
         "网易(杭州)网络有限公司" ,
         "阿里巴巴(中国)有限公司" ,
         "上海希格斯网络科技有限公司" ,
         "running man" ,
         "chicken run" ,
         "tom runs fast"
     };
     for  ( int  i =  0 ; i< orgNames.length; i++) {
       ESOrganization organization =  new  ESOrganization();
       organization.setId(Long.valueOf(i+ 1 ));
       organization.setName(orgNames[i]);
       organization.setType(i *  1 );
       organization.setIndustrialModeCodes( new  Integer[]{ 1 +i,  20 +i,  30 +i});
       organization.setUpdatedAt( new  Date());
       index(client, organization);
     }
   }
   
   public  static  void  main(String[] args)  throws  Exception {
     TransportClient client =  null ;
     try  {
       client = buildClient();
       createOrgMapping(client);
       addIndex(client);
       update(client, getUpdateOrg());
       getById(client,  "1" );
       multiGet(client,  "2" "3" );
       deleteById(client,  "8" );
       //索引创建成功之后1秒钟左右,才会变得可用
       TimeUnit.SECONDS.sleep( 1 );
       search(client, getSearchReq());
     finally  {
       closeClient(client);
     }
     
     
     
   }
   private  static  OrgSearchReq getSearchReq() {
     OrgSearchReq req =  new  OrgSearchReq();
     req.setKeyword( new  String[]{ "阿里巴巴" "乐视" });
     req.setTypes(Arrays.asList( 3 ));
     req.setIndustrialModeCodes(Arrays.asList( 23 , 33 ));
     req.setUpdatedAt( new  Date[]{ null new  Date()});
     return  req;
   }
}
package  com.tch.test.elasticsearch.test;
import  java.util.Date;
public  class  ESOrganization {
   private  Long id;
   private  String name;
   private  Integer type;
   private  Integer[] industrialModeCodes;
   private  Date updatedAt;
   public  Long getId() {
     return  id;
   }
   public  void  setId(Long id) {
     this .id = id;
   }
   public  String getName() {
     return  name;
   }
   public  void  setName(String name) {
     this .name = name;
   }
   public  Integer getType() {
     return  type;
   }
   public  void  setType(Integer type) {
     this .type = type;
   }
   public  Integer[] getIndustrialModeCodes() {
     return  industrialModeCodes;
   }
   public  void  setIndustrialModeCodes(Integer[] industrialModeCodes) {
     this .industrialModeCodes = industrialModeCodes;
   }
   public  Date getUpdatedAt() {
     return  updatedAt;
   }
   public  void  setUpdatedAt(Date updatedAt) {
     this .updatedAt = updatedAt;
   }
}
package  com.tch.test.elasticsearch.test;
import  java.util.Date;
import  java.util.List;
public  class  OrgSearchReq {
   private  String[] keyword;
   private  List types;
   private  List industrialModeCodes;
   private  Date[] updatedAt;
   private  Integer page;
   private  Integer size;
   private  String sortField;
   private  String sortType;
   private  static  final  int  FIRST_PAGE =  1 ;
   private  static  final  int  PAGE_SIZE =  10 ;
   public  String[] getKeyword() {
     return  keyword;
   }
   public  void  setKeyword(String[] keyword) {
     this .keyword = keyword;
   }
   public  List getTypes() {
     return  types;
   }
   public  void  setTypes(List types) {
     this .types = types;
   }
   public  List getIndustrialModeCodes() {
     return  industrialModeCodes;
   }
   public  void  setIndustrialModeCodes(List industrialModeCodes) {
     this .industrialModeCodes = industrialModeCodes;
   }
   public  Date[] getUpdatedAt() {
     return  updatedAt;
   }
   public  void  setUpdatedAt(Date[] updatedAt) {
     this .updatedAt = updatedAt;
   }
   public  Integer getPage() {
     if  (page ==  null  || page <  0 ) {
       return  FIRST_PAGE;
     }
     return  page;
   }
   public  void  setPage(Integer page) {
     this .page = page;
   }
   public  Integer getSize() {
     if  (size ==  null  || size <  0 ) {
       return  PAGE_SIZE;
     }
     return  size;
   }
   public  void  setSize(Integer size) {
     this .size = size;
   }
   public  String getSortField() {
     return  sortField;
   }
   public  void  setSortField(String sortField) {
     this .sortField = sortField;
   }
   public  String getSortType() {
     return  sortType;
   }
   public  void  setSortType(String sortType) {
     this .sortType = sortType;
   }
   public  int  getOffset() {
     return  (getPage() -  1 ) * getSize();
   }
}

 

4.demo解释:

上面的demo中,ESOrganization.java为存到es中的数据结构,OrgSearchReq.java为搜索的条件包装类。

简单的CRUD就不说了,下面主要说一下搜索(search)的部分:

搜索中使用了

BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();

在搜索条件复杂的情况下,我们只需要根据自己的需求使用 BoolQueryBuilder 的 must 和 should来添加 query 的条件,

这里的 must 类似 sql 中的 and, should 类似 sql 中的 or

例如上面的demo中:

BoolQueryBuilder orgQueryBuilder = QueryBuilders.boolQuery();
if  (searchReq.getKeyword() !=  null  && searchReq.getKeyword().length >  0 ) {
   BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
   for  (String keyword : searchReq.getKeyword()) {
     queryBuilder.should(QueryBuilders.matchQuery( "name" , keyword));
   }
   orgQueryBuilder.must(queryBuilder);
}
if  (!CollectionUtils.isEmpty(searchReq.getTypes())) {
   BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
   for  (Integer type : searchReq.getTypes()) {
     queryBuilder.should(QueryBuilders.matchQuery( "type" , type));
   }
   orgQueryBuilder.must(queryBuilder);
}
if  (!CollectionUtils.isEmpty(searchReq.getIndustrialModeCodes())) {
     BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
     for  (Integer industrialMode : searchReq.getIndustrialModeCodes()) {
       queryBuilder.should(QueryBuilders.matchQuery( "industrialModeCodes" , industrialMode));
     }
     orgQueryBuilder.must(queryBuilder);
   }
if  (searchReq.getUpdatedAt() !=  null  && searchReq.getUpdatedAt().length >  0 ) {
     if  (searchReq.getUpdatedAt()[ 0 ] !=  null ) {
       orgQueryBuilder.must(QueryBuilders.rangeQuery( "updatedAt" ).from(searchReq.getUpdatedAt()[ 0 ]));
     }
     if  (searchReq.getUpdatedAt().length ==  2  && searchReq.getUpdatedAt()[ 1 ] !=  null ) {
       orgQueryBuilder.must(QueryBuilders.rangeQuery( "updatedAt" ).to(searchReq.getUpdatedAt()[ 1 ]));
     }
   }
if  (StringUtils.isEmpty(searchReq.getSortField())) {
   searchReq.setSortField( "updatedAt" );
}

 

对应到sql语句就是:

where  ( name  'xxx1'  or  name  'xxx2' and  (type = xxx3  or  type = xxx4)  and  (industrialModeCodes = xxx5  or  industrialModeCodes = xxx6)  and  updatedAt > xxx7  and  updatedAt < xxx8
.addSort(searchReq.getSortField(), getSortOrder(searchReq.getSortType()))
.setFrom(searchReq.getOffset())
.setSize(searchReq.getSize())

对应的就是sql中的排序和分页。

但有一点不同就是

QueryBuilders.matchQuery( "name" , keyword)

和sql中的 name=xxx还有一点不同,因为前者会做分词,例如name为'小米有限公司' 经过分词之后,我们使用matchQuery搜索的时候,keyword输入 '小米' 也能搜到这个记录。

如果要完全等同,那就要使用:

QueryBuilders.termQuery( "name" "小米" )

termQuery不会使用分词,而会使用精确匹配。

范围搜索则是使用rangeQuery:

QueryBuilders.rangeQuery( "updatedAt" ).from(xxx)

 

5.查看索引的mapping:

http://localhost:9200/test/organization/_mapping?pretty

 

6.查看索引中的记录:

http://localhost:9200/test/organization/_search?pretty

 

7.es中index和type的区别

https://www.elastic.co/blog/index-vs-type

 

 8.

2.0之后,filter已经和query合并:

https://www.elastic.co/blog/better-query-execution-coming-elasticsearch-2-0

 

9.elastic如何trouble shooting:

https://www.elastic.co/blog/found-beginner-troubleshooting

 

 

 

你可能感兴趣的:(elastic,search,es,java,api)