elasticsearch 常见查询及聚合分组JAVA API参考

用JAVA+ 微服务客户端写的一些查询,最近一直在研究ELK,对于 elasticsearch是特别感兴趣,并且是用得最多的,现在总结一下一些相关的 CURD语句,帮助我们快速完成一些常用数据分板等。

1 连接客户端的方式  有x-pack插件方式和没有安装插件方式不一样请对号入座,如果是生产上建议安装安全插件x-pack,

private static TransportClient  client;
	
	public static TransportClient getEsClient(){
		//的是没有安装x-pack插件连接方式
		Settings settings = Settings.builder().put("cluster.name","elasticsearch")//设置ES实例的名称
          .put("client.transport.sniff", true) //自动嗅探整个集群的状态,把集群中其他ES节点的ip添加到本地的客户端列表中
          .build();
	
	   
		client = new PreBuiltTransportClient(settings);//连接方式不一样,与x-pack插件有关
		try {
		   client.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.11.237"),9300));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
				
		  System.out.println("ElasticsearchClient 连接成功");
		return client;
}

	public static void closeClient(){
		if(client!=null){
			client.close();
		}
	}

2  建立索引和插入数据 

	public  void insert(){
			Map<String, String> map= new HashMap<String,String>();
			map.put("prodId", "8");
			map.put("prodName", "iphone8s");
			map.put("prodDesc", "智能手机3");
			client = ElasticsearchUtils.getEsClient();
			//索引值不能有大写,同一个索引,类型必须相同, 要在同一个索引名称和类型下增加多数据,索引id必须不同,否则会覆盖
			IndexResponse indexrespone = client.prepareIndex().setIndex(ElasticsearchUtils.getIndexName())//demo_index
			.setType(ElasticsearchUtils.getTypeName())//同一个索引,类型必须相同
			.setSource(map)
			.setId("8")//相同索引类型,ID必须不一样
			.execute()
			.actionGet();
			System.out.println("插入成功, isCreated="+indexrespone.getResult().toString());
			ElasticsearchUtils.closeClient();
		}

	//增加
	public  void insert2(){
		Map<String, String> map= new HashMap<String,String>();
		map.put("name", "Jon someth_test");
		map.put("gender", "male_test");
		//获取服务器实态
		client = ElasticsearchUtils.getEsClient();
		//索引值不能有大写,同一个索引,类型必须相同, 要在同一个索引名称和类型下增加多数据,索引id必须不同,否则会覆盖
		IndexResponse indexrespone = client.prepareIndex("index","type","2")//有不同参数构造函数
		.setSource(map).get();//相同索引类型,ID必须不一样
		System.out.println("插入成功, isCreated="+indexrespone.getResult().toString());
		ElasticsearchUtils.closeClient();
	}

2 查询索引下的所有数据,所有字段包含要查询的内容

	//查询
	public void query(){
		client = ElasticsearchUtils.getEsClient();
		//搜索数据
        GetResponse response = client.prepareGet("blog", "article", "2").execute().actionGet();
        System.out.println("blog get="+response.getSourceAsString());
        //GetResponse responssse = client.prepareGet("java_demo_index", "java_demo_type", "1").execute().actionGet();
		GetResponse getResponse = client.prepareGet().setIndex(ElasticsearchUtils.getIndexName())
				.setType(ElasticsearchUtils.getTypeName())
				.setId("1").execute().actionGet();
		System.out.println("java_demo_index get="+getResponse.getSourceAsString());
		ElasticsearchUtils.closeClient();
	}

public void search(){
			client = ElasticsearchUtils.getEsClient();
			QueryBuilder query = QueryBuilders.queryStringQuery("iphone8s");
			SearchResponse searchResponse = client.prepareSearch("demo_index")//ElasticsearchUtils.getIndexName()
					.setQuery(query)
				  //.setOperationThreaded(false) operationThreaded 设置为 true 是在不同的线程里执行此次操作,配置线程
					.setFrom(0).setSize(10)//相当于limit 
					.execute()
					.actionGet();
			//operationThreaded 设置为 true 是在不同的线程里执行此次操作
			//SearchHits是SearchHit的复数形式,表示这个是一个列表
			SearchHits shs = searchResponse.getHits();
			for(SearchHit hit : shs){
				System.out.println(hit.getSourceAsString());
			}
		   ElasticsearchUtils.closeClient();
		}

3 包含查询和范围查询 

public void search2(){
			client = ElasticsearchUtils.getEsClient();
			QueryBuilder query2 = QueryBuilders.boolQuery()
					.must(QueryBuilders.matchQuery("catId", "6"))
					.must(QueryBuilders.termsQuery("catId", "6","7","8"))// 包含查询  第一个参数是字段后面是包含的数据  相当于  sql里的  in(6,7,8)
					.must(QueryBuilders.rangeQuery("prodId").gte(5));//lte(5)小于等于5,gte(5)大于等于5的数据
			SearchResponse searchRespone2 = client.prepareSearch(ElasticsearchUtils.getIndexName())
					.setQuery(query2)
					.setFrom(0).setSize(10)
					.execute()
					.actionGet();
			SearchHits shs = searchRespone2.getHits();
			for(SearchHit hit :shs){
				System.out.println(hit.getSourceAsString());
			}
			ElasticsearchUtils.closeClient();
		}
//多字段条件查询
   QueryBuilder qb = multiMatchQuery("mac","description","name"); //mac是要搜索的词 description,name 都是字段  与termsQuery 正好相反的作用

List<String> strs=new ArrayList<>();
        strs.add("kimchy14");
        strs.add("kimchy15");
        strs.add("kimchy16");
        QueryBuilder qb=QueryBuilders.termsQuery("user",strs);
 
        SearchRequestBuilder sv=client.prepareSearch("accounts").setTypes("person").setQuery(qb).setFetchSource("age",null).setFrom(0)
                .setSize(100);
        logger.log(Level.INFO,sv.toString());
        SearchResponse response=  sv.get();
        SearchHits searchHits =  response.getHits();
        for(SearchHit hit:searchHits.getHits()){
            logger.log(Level.INFO , hit.getSourceAsString());
        }

4专门按id进行的包含查询

QueryBuilder qb=QueryBuilders.idsQuery(0+"");
 
        SearchRequestBuilder sv=client.prepareSearch("accounts").setTypes("person").setQuery(qb).setFetchSource("age",null).setFrom(0)
                .setSize(100);
        logger.log(Level.INFO,sv.toString());
        SearchResponse response=  sv.get();
        SearchHits searchHits =  response.getHits(); 
        for(SearchHit hit:searchHits.getHits()){
            logger.log(Level.INFO , hit.getSourceAsString());
        }

5 按通配符查询 或是模糊查询 通配符只能加在中间或者末尾 不能加在开头   

  QueryBuilder qb = QueryBuilders.wildcardQuery("user", "k*hy17*");
         //Fuzziness fuzziness=Fuzziness.fromEdits(2);
 
      // QueryBuilder qb = QueryBuilders.fuzzyQuery("user","mchy2").fuzziness(fuzziness);
        //QueryBuilder qb = QueryBuilders.prefixQuery("user", "kimchy2");
        SearchRequestBuilder sv=client.prepareSearch("accounts").setTypes("person").setQuery(qb).setFetchSource("user",null).setFrom(0)
                .setSize(100);
        logger.log(Level.INFO,sv.toString());
        SearchResponse response=  sv.get();
        SearchHits searchHits =  response.getHits();
        for(SearchHit hit:searchHits.getHits()){
            logger.log(Level.INFO , hit.getSourceAsString());
        }

Fuzzy Query 模糊查询
QueryBuilder qb = fuzzyQuery(
    "name",     
    "kimzhy"    
)

6 过滤和排序

//过滤 和排序
		public void filter(){
			client = ElasticsearchUtils.getEsClient();
			//设置查询参数,年龄条件,要求是from,大于50 to 小于60  返回的列表
			//排序 multi_field 
			QueryBuilder  postfilter = QueryBuilders.rangeQuery("prodId").gte(5).lte(8);
			SearchResponse searchrespone = client.prepareSearch(ElasticsearchUtils.getIndexName())
					.setPostFilter(postfilter)
					.setFrom(0).setSize(10)
					.addSort("prodId.keyword",SortOrder.DESC)
					.execute()
					.actionGet();  
			//SearchHits是SearchHit的复数形式,表示这个是一个列表
			SearchHits shs = searchrespone.getHits();
			for(SearchHit hit:shs){
				System.out.println(hit.getSourceAsString());
			}
			ElasticsearchUtils.closeClient();
		}

7 删除和查询删除批量删除等

//通过查询条件删除
		public void deleteSearch(){
			BulkByScrollResponse response =
			    DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
			        .filter(QueryBuilders.matchQuery("gender", "male")) //查询条件
			        .source("persons") //index(索引名)
			        .get();  //执行
			long deleted = response.getDeleted(); //删除文档的数量
		 }
		//如果需要执行的时间比较长,可以使用异步的方式处理,结果在回调里面获取
		public void deleteSearchBatch(){
			DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
		    .filter(QueryBuilders.matchQuery("gender", "male"))      //查询            
		    .source("persons")                //index(索引名)                                    
		    .execute(new ActionListener<BulkByScrollResponse>() {     //回调监听     
		        @Override
		        public void onResponse(BulkByScrollResponse response) {
		            long deleted = response.getDeleted();   //删除文档的数量                 
		        }
		        @Override
		        public void onFailure(Exception e) {
		            // Handle the exception
		        }
		    });
		}

8   Upsert有数据就更新, 无数据就插入

 //Upsert   更新插入,如果存在文档就更新,如果不存在就插入
		public void updateInsert() throws IOException{
	    	client = ElasticsearchUtils.getEsClient();
	    	XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();//帮助类,转成 json格式
	    	IndexRequest indexRequest = new IndexRequest("index", "type")//可以省掉ID号, 默认查询所有索引ID
	    	        .source(jsonBuilder     //此处查询条件可以省掉,默认查询所有属性类型
	    	                .startObject()
	    	                .field("name", "Jon someth_test")
	    	                .field("gender", "male_test")
	    	            .endObject());
	    	UpdateRequest updateRequest = new UpdateRequest("index", "type", "2")
	    	        .doc(XContentFactory.jsonBuilder()       //必须是新的实例,坑了很久,下面是更新的属性,没有的这个属性就增加,如果有就更新
	    	                .startObject()
	    	                .field("gender", "male_copy_test")
	    	            .endObject())
	    	        .upsert(indexRequest); //如果不存在此文档 ,就增加 `indexRequest`
	    	try {
				client.update(updateRequest).get();
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
	    }

9 批量操作

//使用 Bulk Processor
		//BulkProcessor 提供了一个简单的接口,在给定的大小数量上定时批量自动请求
		public void BulkProcessor() throws IOException{
			Client client = ElasticsearchUtils.getEsClient();
			BulkProcessor bulkProcessor = BulkProcessor.builder(
			        client,  //增加elasticsearch客户端
			        new BulkProcessor.Listener() {
			            @Override
			            public void beforeBulk(long executionId,
			                                   BulkRequest request) { System.out.println("执行前调用方法"); } //调用bulk之前执行 ,例如你可以通过request.numberOfActions()方法知道numberOfActions
			            @Override
			            public void afterBulk(long executionId,
			                                  BulkRequest request,
			                                  BulkResponse response) { System.out.println("执行后调用方法");  } //调用bulk之后执行 ,例如你可以通过request.hasFailures()方法知道是否执行失败
			            @Override
			            public void afterBulk(long executionId,
			                                  BulkRequest request,
			                                  Throwable failure) {  System.out.println("执行失败抛Throwable调用方法"); } //调用失败抛 Throwable
			        })
			        .setBulkActions(10000) //每次10000请求
			        .setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB)) //拆成5mb一块
			        .setFlushInterval(TimeValue.timeValueSeconds(5)) //无论请求数量多少,每5秒钟请求一次。
			        .setConcurrentRequests(1) //设置并发请求的数量。值为0意味着只允许执行一个请求。值为1意味着允许1并发请求。
			        .setBackoffPolicy(
			            BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))//设置自定义重复请求机制,最开始等待100毫秒,之后成倍更加,重试3次,当一次或多次重复请求失败后因为计算资源不够抛出 EsRejectedExecutionException 异常,可以通过BackoffPolicy.noBackoff()方法关闭重试机制
			        .build();
         /* BulkProcessor 默认设置
  			bulkActions  1000 
			bulkSize 5mb
			不设置flushInterval
			concurrentRequests 为 1 ,异步执行
			backoffPolicy 重试 8次,等待50毫秒*/
			bulkProcessor.add(new IndexRequest("twitter", "tweet", "1").source("your doc here 需要插入的文件和资源"));
			bulkProcessor.add(new DeleteRequest("twitter", "tweet", "2"));//删除一个索引 
			bulkProcessor.close();  //关闭操作
		}

10  Stats 聚合操作 count min max avg sum 

 private static void stats(TransportClient client) {
        SearchRequestBuilder search = client.prepareSearch("mytest_1").setTypes("test");
        SearchResponse sr =  search.addAggregation(AggregationBuilders.stats("price_stats").field("price")).execute().actionGet();

       Stats stats = sr.getAggregations().get("price_stats");
        System.out.println(stats.getAvgAsString());
        System.out.println(stats.getMaxAsString());
        System.out.println(stats.getMinAsString());
        System.out.println(stats.getSumAsString());

    }

这些是一些日常用到的方法,熟练使用后基本没有什么问题,当然还有更多操作数据的方法,我就不上传了,在github上放着

最后总结如下    精确查询用term 组合查询用bool 范围用range    and查询用must    or查询用should  not查询用must not  常见的接收聚合返回结果的类型 ValueCount   AVG  SUM  MAX  MIN  按照英文意义就可以理解  分组聚合查询时候还需要根据实际情况看是返回那种terms 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值