elasticsearch java API

springboot-elasticsearch

基于springboot的web項目,通過elasticsearch提供的Java API 進行查詢操作.

起因

項目在一個查詢要在亞秒級計算(分組、累加、平均)大量數據的結果。官方提供的API過于簡單,自己在做項目中遇到了一些坑,并總結了一些API的使用,簡單分享一下。

前置條件

有一個elasticsearch服務

配置

demo是基于springboot快速構建了一個web應用。elasticsearch提供了一個客戶端:TransportClient,首先我們來配置一下

如果在main方法里面執行可以直接創建一個客戶端連接
TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("172.16.3.121"), 9300));
如果在springboot項目中。配置一下,這樣我們可以直接注入使用了。
@Configuration
public class ElasticSearchConfig {

    @Value("${spring.elasticsearch.host}")
    private String host;//elasticsearch的地址

    @Value("${spring.elasticsearch.port}")
    private Integer port;//elasticsearch的端口

    private static final Logger LOG = LogManager.getLogger(ElasticSearchConfig.class);

    @Bean
    public TransportClient client(){
        TransportClient client = null;
        try {

            client = new PreBuiltTransportClient(Settings.EMPTY)
                    .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port));
        } catch (UnknownHostException e) {
            LOG.error("創建elasticsearch客戶端失敗");
            e.printStackTrace();
        }
        LOG.info("創建elasticsearch客戶端成功");
        return client;
    }

}

配置完畢之后,我們就可以使用了。這里寫了一個簡單的demo,匯總了常用的一些API使用。

代碼示例

這個代碼示例滿足了查詢所需,查詢條件,分組計算,分組排序等

    Map<String,Object> map = Collections.emptyMap();

        Script script = new Script(ScriptType.INLINE, "painless","params._value0 > 0",map);  //提前定義好查詢銷量是否大于1000的腳本,類似SQL里面的having

        long beginTime = System.currentTimeMillis();

        SearchResponse sr = client.prepareSearch("adele").setTypes("sale")
                .setQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("store_name.keyword", "xxx旗艦店"))  //挨個設置查詢條件,沒有就不加,如果是字符串類型的,要加keyword后綴
                        .must(QueryBuilders.termQuery("department_name.keyword", "玎"))
                        .must(QueryBuilders.termQuery("category_name.keyword", "T恤"))
                        .must(QueryBuilders.rangeQuery("pay_date").gt("2017-03-07").lt("2017-07-09"))
                ).addAggregation(
                        AggregationBuilders.terms("by_product_code").field("product_code.keyword").size(500) //按貨號分組,最多查500個貨號.SKU直接改字段名字就可以
                                .subAggregation(AggregationBuilders.terms("by_store_name").field("store_name.keyword").size(50) //按店鋪分組,不顯示店鋪可以過濾掉這一行,下邊相應減少一個循環
                                        .subAggregation(AggregationBuilders.sum("total_sales").field("quantity"))  //分組計算銷量匯總
                                        .subAggregation(AggregationBuilders.sum("total_sales_amount").field("amount_actual"))  //分組計算實付款匯總,需要加其他匯總的在這里依次加
                                        .subAggregation(PipelineAggregatorBuilders.bucketSelector("sales_bucket_filter",script,"total_sales")))//查詢是否大于指定值
                                .order(Terms.Order.compound(Terms.Order.aggregation("total_calculate_sale_amount",false)))) //分組排序

                .execute().actionGet();

        Terms terms = sr.getAggregations().get("by_product_code");   //查詢遍歷第一個根據貨號分組的aggregation

        System.out.println(terms.getBuckets().size());
        for (Terms.Bucket entry : terms.getBuckets()) {
            System.out.println("------------------");
            System.out.println("【 " + entry.getKey() + " 】訂單數 : " + entry.getDocCount() );

            Terms subTerms = entry.getAggregations().get("by_store_name");    //查詢遍歷第二個根據店鋪分組的aggregation
            for (Terms.Bucket subEntry : subTerms.getBuckets()) {
                Sum sum1 = subEntry.getAggregations().get("total_sales"); //取得銷量的匯總
                double total_sales = sum1.getValue();
                System.out.println(subEntry.getKey() + " 訂單數:  " + subEntry.getDocCount() + "  銷量: " + total_sales); //店鋪和訂單數量和銷量
            }
        }

        long endTime = System.currentTimeMillis();
        System.out.println("查詢耗時" + ( endTime - beginTime ) + "毫秒");
    

demo地址

springboot-elasticsearch

  1. 啟動項目
  2. 訪問http://localhost:9999/test
  3. 查看后端打印

參考鏈接

Search API

有一些坑是我領導踩得,部分代碼已得授權。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容