码迷,mamicode.com
首页 > 其他好文 > 详细

ElasticSearch入门之彼行我释(四)

时间:2015-03-17 12:44:30      阅读:635      评论:0      收藏:0      [点我收藏+]

标签:


技术分享

散仙在上篇文章中,介绍了关于ElasticSearch基本的增删改查的基本粒子,本篇呢,我们来学下稍微高级一点的知识: 


(1)如何在ElasticSearch中批量提交索引 ? 
(2)如何使用高级查询(包括,检索,排序,过滤,分页) ? 
(3)如何组合多个查询 ? 
(4)如何使用翻页深度查询 ? 
(5)如何使用基本的聚合查询 ? 



(一)首先,我们思考下,为什么要使用批量添加,这个毫无疑问,因为效率问题,举个在生活中的例子,假如我们有50个人,要去美国旅游,不使用批处理的方式是,给每一个人派一架飞机送到美国,那么这就需要50次飞机的来回往来,假如使用了批处理,现在的情况就是一个飞机坐50个人,只需一次即可把所有人都送到美国,效率可想而知,生活也有很多实际的例子,大家可以自己想想。 

在原生的lucene中,以及solr中,这个批处理方式,实质是控制commit的时机,比如多少个提交一次,或者超过ranbuffersize的大小后自动提交,es封装了lucene的api提供bulk的方式来批量添加,原理也是,聚集一定的数量doc,然后发送一次添加请求。 


(二)只要我们使用了全文检索,我们的业务就会有各种各样的api操作,包括,任意维度的字段查询,过滤掉某些无效的信息,然后根据某个字段排序,再取topN的结果集返回,使用数据库的小伙伴们,相信大家都不陌生,在es中,这些操作都是支持的,而且还非常高效,它能满足我们大部分的需求 


(三)在es中,我们可以查询多个index,以及多个type,这一点是非常灵活地,我们,我们可以一次组装两个毫无关系的查询,发送到es服务端进行检索,然后获取结果。 


(四)es中,通过了scorll的方式,支持深度分页查询,在数据库里,我们使用的是一个cursor游标来记录读取的偏移量,同样的在es中也支持,这样的查询方式,它通过一个scrollid记录了上一次查询的状态,能轻而易举的实现深度翻页,本质上是对了Lucene的SearchAfter的封装。 

(五)es中,也提供了对聚合函数的支持,比如一些max,min,avg,count,sum等支持,除此之外还支持group,facet等操作,这些功能,在电商中应用非常广泛,基于lucene的solr和es都有很好的支持。 

下面截图看下散仙的测试数据值: 


技术分享
源码demo如下: 

   

  1. import java.util.Date;  

  2. import java.util.Map;  

  3. import java.util.Map.Entry;  

  4.   

  5. import org.apache.lucene.index.Terms;  

  6. import org.elasticsearch.action.bulk.BulkRequestBuilder;  

  7. import org.elasticsearch.action.bulk.BulkResponse;  

  8. import org.elasticsearch.action.search.MultiSearchResponse;  

  9. import org.elasticsearch.action.search.SearchRequestBuilder;  

  10. import org.elasticsearch.action.search.SearchResponse;  

  11. import org.elasticsearch.action.search.SearchType;  

  12. import org.elasticsearch.client.Client;  

  13. import org.elasticsearch.client.transport.TransportClient;  

  14. import org.elasticsearch.common.transport.InetSocketTransportAddress;  

  15. import org.elasticsearch.common.unit.TimeValue;  

  16. import org.elasticsearch.common.xcontent.XContentBuilder;  

  17. import org.elasticsearch.common.xcontent.XContentFactory;  

  18. import org.elasticsearch.index.query.FilterBuilders;  

  19. import org.elasticsearch.index.query.QueryBuilders;  

  20. import org.elasticsearch.index.query.QueryStringQueryBuilder;  

  21. import org.elasticsearch.search.SearchHit;  

  22. import org.elasticsearch.search.aggregations.AggregationBuilders;  

  23. import org.elasticsearch.search.aggregations.bucket.filters.InternalFilters.Bucket;  

  24. import org.elasticsearch.search.sort.SortOrder;  

  25.   

  26. /** 

  27.  * @author 三劫散仙 

  28.  * 搜索技术交流群:324714439  

  29.  * 一个关于elasticsearch批量提交 

  30.  * 和search query的的例子 

  31.  * **/  

  32. public class ElasticSearchDao {  

  33.       

  34.       

  35.     //es的客户端实例  

  36.     Client client=null;  

  37.     {  

  38.         //连接单台机器,注意ip和端口号,不能写错  

  39.         client=new TransportClient().  

  40.                 addTransportAddress(new InetSocketTransportAddress("192.168.46.16"9300));  

  41.           

  42.     }  

  43.       

  44.       

  45.     public static void main(String[] args)throws Exception {  

  46.         ElasticSearchDao es=new ElasticSearchDao();  

  47.         //es.indexdata();//索引数据  

  48.         //es.queryComplex();  

  49.         es.querySimple();  

  50.         //es.scorllQuery();  

  51.         //es.mutilCombineQuery();  

  52.         //es.aggregationQuery();  

  53.     }  

  54.       

  55.       

  56.     /**组合分组查询*/  

  57.     public void aggregationQuery()throws Exception{  

  58.         SearchResponse sr = client.prepareSearch()  

  59.                 .setQuery(QueryBuilders.matchAllQuery())  

  60.                 .addAggregation(  

  61.                         AggregationBuilders.terms("1").field("type")  

  62.                 )  

  63. //              .addAggregation(  

  64. //                      AggregationBuilders.dateHistogram("agg2")  

  65. //                              .field("birth")  

  66. //                              .interval(DateHistogram.Interval.YEAR)  

  67. //              )  

  68.                 .execute().actionGet();  

  69.   

  70.             // Get your facet results  

  71.             org.elasticsearch.search.aggregations.bucket.terms.Terms a = sr.getAggregations().get("1");  

  72.               

  73.             for(org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket bk:a.getBuckets()){  

  74.                 System.out.println("类型: "+bk.getKey()+"  分组统计数量 "+bk.getDocCount()+"  ");  

  75.             }  

  76.               

  77.             System.out.println("聚合数量:"+a.getBuckets().size());  

  78.             //DateHistogram agg2 = sr.getAggregations().get("agg2");  

  79.             //结果:  

  80. //          类型: 1  分组数量 2    

  81. //          类型: 2  分组数量 1    

  82. //          类型: 3  分组数量 1    

  83. //          聚合数量:3  

  84.     }  

  85.       

  86.       

  87.       

  88.       

  89.     /**多个不一样的请求组装*/  

  90.     public void mutilCombineQuery(){  

  91.           

  92.         //查询请求1  

  93.         SearchRequestBuilder srb1 =client.prepareSearch().setQuery(QueryBuilders.queryString("eng").field("address")).setSize(1);  

  94.         //查询请求2//matchQuery  

  95.         SearchRequestBuilder srb2 = client.prepareSearch().setQuery(QueryBuilders.matchQuery("title""标题")).setSize(1);  

  96.         //组装查询  

  97.         MultiSearchResponse sr = client.prepareMultiSearch().add(srb1).add(srb2).execute().actionGet();  

  98.   

  99.             // You will get all individual responses from MultiSearchResponse#getResponses()  

  100.             long nbHits = 0;  

  101.             for (MultiSearchResponse.Item item : sr.getResponses()) {  

  102.                 SearchResponse response = item.getResponse();  

  103.                 for(SearchHit hits:response.getHits().getHits()){  

  104.                     String sourceAsString = hits.sourceAsString();//以字符串方式打印  

  105.                     System.out.println(sourceAsString);  

  106.                 }  

  107.                 nbHits += response.getHits().getTotalHits();  

  108.             }  

  109.         System.out.println("命中数据量:"+nbHits);  

  110.         //输出:  

  111. //      {"title":"我是标题","price":25.65,"type":1,"status":true,"address":"血落星域风阳星","createDate":"2015-03-16T09:56:20.440Z"}  

  112. //      命中数据量:2  

  113.   

  114.         client.close();  

  115.     }  

  116.       

  117.       

  118.     /** 

  119.      * 翻页查询 

  120.      * */  

  121.     public void scorllQuery()throws Exception{  

  122.         QueryStringQueryBuilder queryString = QueryBuilders.queryString("标题").field("title");  

  123.         //TermQueryBuilder qb=QueryBuilders.termQuery("title", "我是标题");  

  124.         SearchResponse scrollResp = client.prepareSearch("collection1")  

  125.                  .setSearchType(SearchType.SCAN)  

  126.                  .setScroll(new TimeValue(60000))  

  127.                  .setQuery(queryString)  

  128.                  .setSize(100).execute().actionGet(); //100 hits per shard will be returned for each scroll  

  129.            

  130.           

  131.         while (true) {  

  132.             for (SearchHit hit : scrollResp.getHits().getHits()) {  

  133.                 //Handle the hit...  

  134.                 String sourceAsString = hit.sourceAsString();//以字符串方式打印  

  135.                 System.out.println(sourceAsString);  

  136.             }  

  137.             //通过scrollid来实现深度翻页  

  138.             scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(600000)).execute().actionGet();  

  139.             //Break condition: No hits are returned  

  140.             if (scrollResp.getHits().getHits().length == 0) {  

  141.                 break;  

  142.             }  

  143.         }  

  144.         //输出  

  145. //      {"title":"我是标题","price":25.65,"type":1,"status":true,"address":"血落星域风阳星","createDate":"2015-03-16T09:56:20.440Z"}  

  146. //      {"title":"标题","price":251.65,"type":1,"status":true,"address":"美国东部","createDate":"2015-03-16T10:33:58.743Z"}  

  147.         client.close();  

  148.           

  149.     }  

  150.       

  151.     /**简单查询*/  

  152.     public void querySimple()throws Exception{  

  153.           

  154.         SearchResponse sp = client.prepareSearch("collection1").execute().actionGet();  

  155.         for(SearchHit hits:sp.getHits().getHits()){  

  156.             String sourceAsString = hits.sourceAsString();//以字符串方式打印  

  157.             System.out.println(sourceAsString);  

  158.         }  

  159.           

  160.           

  161.     //结果  

  162. //              {"title":"我是标题","price":25.65,"type":1,"status":true,"address":"血落星域风阳星","createDate":"2015-03-16T09:56:20.440Z"}  

  163. //              {"title":"中国","price":205.65,"type":2,"status":true,"address":"河南洛阳","createDate":"2015-03-16T10:33:58.740Z"}  

  164. //              {"title":"标题","price":251.65,"type":1,"status":true,"address":"美国东部","createDate":"2015-03-16T10:33:58.743Z"}  

  165. //              {"title":"elasticsearch是一个搜索引擎","price":25.65,"type":3,"status":true,"address":"china","createDate":"2015-03-16T10:33:58.743Z"}  

  166.   

  167.           

  168.     }  

  169.     /**组合查询**/  

  170.     public void queryComplex()throws Exception{  

  171.         SearchResponse sp=client.prepareSearch("collection1")//检索的目录  

  172.                 .setTypes("core1")//检索的索引  

  173.                 .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)//Query type  

  174.                 .setQuery(QueryBuilders.termQuery("type""1"))//查询--Query   

  175.                 .setPostFilter(FilterBuilders.rangeFilter("price").from(10).to(550.23))//过滤 --Filter  

  176.                 .addSort("price",SortOrder.DESC) //排序 -- sort  

  177.                 .setFrom(0).setSize(20).setExplain(true)//topN方式  

  178.                 .execute().actionGet();//执行  

  179.                 System.out.println("本次查询命中条数: "+sp.getHits().getTotalHits());  

  180.                 for(SearchHit hits:sp.getHits().getHits()){  

  181.                     //String sourceAsString = hits.sourceAsString();//以字符串方式打印  

  182.                     //System.out.println(sourceAsString);  

  183.                     Map<String, Object> sourceAsMap = hits.sourceAsMap();  

  184.                     for(Entry<String, Object> k:sourceAsMap.entrySet()){  

  185.                         System.out.println("name: "+k.getKey()+"     value: "+k.getValue());  

  186.                     }  

  187.                       

  188.                     System.out.println("=============================================");  

  189.                       

  190.                 }  

  191.           

  192.                 //结果  

  193. //              本次查询命中条数: 2  

  194. //              name: title     value: 标题  

  195. //              name: price     value: 251.65  

  196. //              name: address     value: 美国东部  

  197. //              name: status     value: true  

  198. //              name: createDate     value: 2015-03-16T10:33:58.743Z  

  199. //              name: type     value: 1  

  200. //              =============================================  

  201. //              name: title     value: 我是标题  

  202. //              name: price     value: 25.65  

  203. //              name: address     value: 血落星域风阳星  

  204. //              name: status     value: true  

  205. //              name: createDate     value: 2015-03-16T09:56:20.440Z  

  206. //              name: type     value: 1  

  207. //              =============================================  

  208.           

  209.         client.close();  

  210.     }  

  211.       

  212.       

  213.       

  214.     /**索引数据*/  

  215.     public void indexdata()throws Exception{  

  216.           

  217.         BulkRequestBuilder bulk=client.prepareBulk();  

  218.           

  219.         XContentBuilder doc=XContentFactory.jsonBuilder()  

  220.                 .startObject()  

  221.                 .field("title","中国")  

  222.                 .field("price",205.65)  

  223.                 .field("type",2)  

  224.                 .field("status",true)  

  225.                 .field("address""河南洛阳")  

  226.                 .field("createDate"new Date()).endObject();  

  227.         //collection为索引库名,类似一个数据库,索引名为core,类似一个表  

  228. //       client.prepareIndex("collection1", "core1").setSource(doc).execute().actionGet();  

  229.           

  230.         //批处理添加  

  231.         bulk.add(client.prepareIndex("collection1""core1").setSource(doc));  

  232.           

  233.         doc=XContentFactory.jsonBuilder()  

  234.                 .startObject()  

  235.                 .field("title","标题")  

  236.                 .field("price",251.65)  

  237.                 .field("type",1)  

  238.                 .field("status",true)  

  239.                 .field("address""美国东部")  

  240.                 .field("createDate"new Date()).endObject();  

  241.         //collection为索引库名,类似一个数据库,索引名为core,类似一个表  

  242. //      client.prepareIndex("collection1", "core1").setSource(doc).execute().actionGet();  

  243.         //批处理添加  

  244.         bulk.add(client.prepareIndex("collection1""core1").setSource(doc));  

  245.           

  246.         doc=XContentFactory.jsonBuilder()  

  247.                 .startObject()  

  248.                 .field("title","elasticsearch是一个搜索引擎")  

  249.                 .field("price",25.65)  

  250.                 .field("type",3)  

  251.                 .field("status",true)  

  252.                 .field("address""china")  

  253.                 .field("createDate"new Date()).endObject();  

  254.         //collection为索引库名,类似一个数据库,索引名为core,类似一个表  

  255.         //client.prepareIndex("collection1", "core1").setSource(doc).execute().actionGet();  

  256.         //批处理添加  

  257.         bulk.add(client.prepareIndex("collection1""core1").setSource(doc));         

  258.           

  259.           

  260.         //发一次请求,提交所有数据  

  261.           BulkResponse bulkResponse = bulk.execute().actionGet();  

  262.           if (!bulkResponse.hasFailures()) {  

  263.               System.out.println("创建索引success!");  

  264.           } else {  

  265.               System.out.println("创建索引异常:"+bulkResponse.buildFailureMessage());  

  266.           }  

  267.           

  268.           

  269.           

  270.         client.close();//释放资源  

  271. //      System.out.println("索引成功!");  

  272.                   

  273.           

  274.           

  275.           

  276.     }  

  277.       

  278.       

  279.       

  280.       

  281.   

  282. }  


ElasticSearch入门之彼行我释(四)

标签:

原文地址:http://my.oschina.net/u/1027043/blog/387819

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!