天天看點

elasticsearch的restful API和Java API

本人現在使用的是elasticsearch 5.2.1的,伺服器IP為192.168.5.182.是以在Java API和jar包中會有所不同.

常用的restful API如下:

http://192.168.5.182:9200/_cat/health?v 健康檢查 http://192.168.5.182:9200/_cat/indices?v

檢視索引

PUT

http://192.168.5.182:9200/test_index?pretty

添加索引

DELETE

http://192.168.5.182:9200/test_index 删除索引 http://192.168.5.182:9200/ecommerce/product/1 BODY {

"name":"zhonghua yagao",
"desc":"caoben zhiwu",
"price":40,
"producer":"zhonghua producer",
"tags":["qingxin"]           

} 為索引添加資料,ecommerce索引,product type,1 ID

GET

查詢資料

"name":"jiaqiangban zhonghua yagao",
"desc":"caoben zhiwu",
"price":40,
"producer":"zhonghua producer",
"tags":["qingxin"]           

} 更新索引資料,方式一,必須帶上所有資料

POST

http://192.168.5.182:9200/ecommerce/product/1/_update
"doc": {
    "name":"gaolujie yagao"
}           

} 更新索引資料,方式二

删除索引資料

http://192.168.5.182:9200/ecommerce/product/_search

搜尋所有

http://192.168.5.182:9200/ecommerce/product/_search?q=name:yagao&sort=price:desc

curl -XGET '

' -d'

{

"query":{

"match_all":{}           

}

}'

"query":{
    "match":{
         "name":"yagao"
    }
},
"sort":[
    {"price":"desc"}
]           
}' 排序查詢
"query":{
"match_all":{}           

},

"from":1,

"size":1

}' 分頁查詢

"match_all":{}           

"_source":["name","price"]

}' 隻查詢指定的字段

"query":{
"bool":{
    "must":{
       "match":{
          "name":"yagao"
       }
    },
    "filter":{
       "range":{
          "price":{
             "gt":25
          }
       }
    }
 }           

}' 查詢yagao的price範圍,大于25

curl -XGET '

"match":{
     "producer":"yagao producer"
  }           
}' 全文檢索
"match_phrase":{
     "producer":"yagao producer"
  }           

}' 短語搜尋

"query":{
   "match":{
      "producer":"producer"
   }
},
"highlight":{
   "fields":{
      "producer":{}
   }
}           
}' 高亮顯示 http://192.168.5.182:9200/ecommerce/_mapping/product
"properties":{
    "tags":{
        "type":"text",
        "fielddata":true
    }
}           

} 将文本field的fielddata屬性設定為true

"aggs":{
    "group_by_tags":{
          "terms":{
               "field":"tags"
          }
    }
}           
}' 對tags聚合,會顯示明細

{ "size":0,

"aggs":{
    "group_by_tags":{
          "terms":{
               "field":"tags"
          }
    }
}           

}' 對tags聚合,不顯示明細,隻顯示聚合

"size":0,
"match":{
       "name":"yagao"
   }           
"aggs":{
"group_by_tags":{
       "terms":{
            "field":"tags"
       }
   }           
}' 搜尋包含條件的聚合
"size":0,
"aggs":{
     "group_by_tags":{
          "terms":{
               "field":"tags"
          },
          "aggs":{
               "avg_price":{
                     "avg":{
                           "field":"price"
                     }
               }
          }
     }
}           
}' 聚合計算平均值
"size":0,
"aggs":{
   "group_by_tags":{
       "terms":{
           "field":"tags",
           "order":{
                "avg_price":"desc"
           }
       },
       "aggs":{
           "avg_price":{
                "avg":{
                      "field":"price"
                }
           }
       }
   }
}           
}' 聚合後降序排序
"group_by_price":{
      "range":{
          "field":"price",
          "ranges":[
            {      
               "from":0,
               "to":20
            },        
            {      
               "from":20,
               "to":40
            },        
            {      
               "from":40,
               "to":60
            }
          ]
       },
       "aggs":{
          "group_by_tags":{
             "terms":{
                 "field":"tags"
             },
             "aggs":{
                 "average_price":{
                     "avg":{
                         "field":"price"
                     }
                 }
             }
          }
       }
  }           

}' 按照價格區間分組後再聚合tags平均價格

http://192.168.5.182:9200/company
"mappings": {
        "employee": {
            "properties": {
                "age": {
                    "type": "long"
                },
                "country": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    },
                    "fielddata":true
                },
                "join_date": {
                    "type": "date"
                },
                "name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "position": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "salary": {
                    "type": "long"
                }
            }
        }
    }           

} 給country建立正排索引

在Java API中,我們需要先找到相應的jar包,maven中的配置如下(開始之前請先執行上面的給country建立正排索引的restful API)

org.elasticsearch.client

transport

5.2.1

5.2.1中隻需要配這一個就可以了,當然不同的版本配置的都不同,高版本的需要配

org.elasticsearch

elasticsearch

我們依然在resources檔案中做如下配置(注意restful API中使用的是9200端口,而Java API使用的是9300端口)

elasticsearch:

clusterName: aubin-cluster

clusterNodes: 192.168.5.182:9300

配置類如下

@Getter

@Setter

@Configuration

@ConfigurationProperties(prefix = "elasticsearch")

public class ElasticSearchConfig {

private String clusterName;

private String clusterNodes;

/**
 * 使用elasticsearch實作類時才觸發
 *
 * @return
 */           

@Bean

public TransportClient transportClient() {

// 設定叢集名字
  Settings settings = Settings.builder().put("cluster.name", this.clusterName).build();
  TransportClient client = new PreBuiltTransportClient(settings);
  try {
     // 讀取的ip清單是以逗号分隔的
     for (String clusterNode : this.clusterNodes.split(",")) {
        String ip = clusterNode.split(":")[0];
        String port = clusterNode.split(":")[1];
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ip), Integer.parseInt(port)));
     }
  } catch (UnknownHostException e) {
     e.printStackTrace();
  }

  return client;           

在5.2.1中使用的是InetSocketTransportAddress,這是一個具體的類,而在高版本中此處為TransportAddress,這是一個接口.

我們做一個資料類

@Component

public class DataEs {

@Autowired
private TransportClient transportClient;

/**
 * 添加原始資料
 * @throws IOException
 */
@PostConstruct
private void init() throws IOException {
    transportClient.prepareIndex("company","employee","1").setSource(XContentFactory.jsonBuilder().startObject()
            .field("name","jack")
            .field("age",27)
            .field("position","technique software")
            .field("country","China")
            .field("join_date","2018-01-01")
            .field("salary",10000)
            .endObject()).get();
    transportClient.prepareIndex("company","employee","2").setSource(XContentFactory.jsonBuilder().startObject()
            .field("name","marry")
            .field("age",35)
            .field("position","technique manager")
            .field("country","China")
            .field("join_date","2018-01-01")
            .field("salary",12000)
            .endObject()).get();
    transportClient.prepareIndex("company","employee","3").setSource(XContentFactory.jsonBuilder().startObject()
            .field("name","tom")
            .field("age",32)
            .field("position","senior technique software")
            .field("country","China")
            .field("join_date","2017-01-01")
            .field("salary",11000)
            .endObject()).get();
    transportClient.prepareIndex("company","employee","4").setSource(XContentFactory.jsonBuilder().startObject()
            .field("name","jen")
            .field("age",25)
            .field("position","junior finance")
            .field("country","USA")
            .field("join_date","2017-01-01")
            .field("salary",7000)
            .endObject()).get();
    transportClient.prepareIndex("company","employee","5").setSource(XContentFactory.jsonBuilder().startObject()
            .field("name","mike")
            .field("age",37)
            .field("position","finance manager")
            .field("country","USA")
            .field("join_date","2016-01-01")
            .field("salary",15000)
            .endObject()).get();
}

/**
 * 員工搜尋應用程式
 * 搜尋職位中包含technique的員工
 * 同時要求age在30到40歲之間
 * 分頁查詢,查找第一頁
 */
public void executeSearch() {
    SearchResponse searchResponse = transportClient.prepareSearch("company")
            .setTypes("employee")
            .setQuery(QueryBuilders.matchQuery("position", "technique"))
            .setPostFilter(QueryBuilders.rangeQuery("age").from(30).to(40))
            .setFrom(0).setSize(1)
            .get();
    SearchHit[] hits = searchResponse.getHits().getHits();
    for (int i = 0;i < hits.length;i++) {
        System.out.println(hits[i].getSourceAsString());
    }
}

/**
 * 員工聚合分析應用程式
 * 首先按照country國家來進行分組
 * 然後在每個country分組内,再按照入職年限進行分組
 * 最後計算每個分組内的平均薪資
 */
public void executeAggregation() {
    SearchResponse searchResponse = transportClient.prepareSearch("company")
            .addAggregation(AggregationBuilders.terms("group_by_country").field("country")
            .subAggregation(AggregationBuilders.dateHistogram("group_by_join_date")
            .field("join_date").dateHistogramInterval(DateHistogramInterval.YEAR)
            .subAggregation(AggregationBuilders.avg("avg_salary").field("salary"))))
            .execute().actionGet();
    Map<String,Aggregation> aggrMap = searchResponse.getAggregations().asMap();
    StringTerms groupByCountry = (StringTerms) aggrMap.get("group_by_country");
    Iterator<StringTerms.Bucket> groupByCountryBucketIterator = groupByCountry.getBuckets().iterator();
    while (groupByCountryBucketIterator.hasNext()) {
        StringTerms.Bucket groupByCountryBucket = groupByCountryBucketIterator.next();
        System.out.println(groupByCountryBucket.getKey() + ":" + groupByCountryBucket.getDocCount());
        Histogram groupByJoinDate = (Histogram) groupByCountryBucket.getAggregations().asMap().get("group_by_join_date");
        Iterator<? extends Histogram.Bucket> groupByJoinDateIterator = groupByJoinDate.getBuckets().iterator();
        while (groupByJoinDateIterator.hasNext()) {
            Histogram.Bucket groupByJoinDateBucket = groupByJoinDateIterator.next();
            System.out.println(groupByJoinDateBucket.getKey() + ":" + groupByJoinDateBucket.getDocCount());
            Avg avg = (Avg) groupByJoinDateBucket.getAggregations().asMap().get("avg_salary");
            System.out.println(avg.getValue());
        }
    }
}
public void close() {
    transportClient.close();
}           

在主程式中調用如下(一般我們可以先不執行搜尋操作,先注入資料,因為elasticsearch本身有一個秒級寫讀的問題,如果資料寫入,得需要1秒的時間才能讀取出來)

@SpringBootApplication

public class EsApplication {

public static void main(String[] args) {

ApplicationContext applicationContext = SpringApplication.run(EsApplication.class, args);
  DataEs dataEs = (DataEs) applicationContext.getBean(DataEs.class);
  dataEs.executeSearch();
  dataEs.executeAggregation();
  dataEs.close();