在瞭解了ES的基礎知識後,接下來就是實際操做了。git
環境準備:
jdk 1.8
ElasticSearch 6.4.0
window7github
步驟:spring
在啓動過程當中默認的jvm內存參數設置比較大,能夠在config目錄下面的jvm.options中將-Xms和-Xmx調小sql
git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
複製代碼
啓動後,能夠在瀏覽器中訪問9100端口npm
經過上述的幾個步驟,咱們就成功的搭建了一個能夠試驗的ES環境,使用header插件能夠更加方便的查看ES中索引,分片和文檔的信息。json
因爲存在跨域問題,因此須要在elasticsearch目錄中config下的elasticsearch.yml文件中添加跨域
http.cors.enabled: true
http.cors.allow-origin: "*"
複製代碼
ES是基於http和json來和客戶端交互的,所以官方也提供了一個RESTClient客戶端,因此咱們也藉助這個client來實現增刪改查的操做。瀏覽器
依賴:bash
org.elasticsearch:elasticsearch:5.4.2 ->ES 平臺版本
org.elasticsearch.client:rest:5.4.2 -> restClient 版本
io.searchbox:jest:5.3.3 -> 基於RestClient的一個封裝
複製代碼
在使用jest時,會建立一個全局單例的JestClient,而後在整個應用的生命週期中都會使用該client多線程
JestClientFactory factory = new JestClientFactory();
List<String> urls = new ArrayList<>();
// urls.add("http://10.37.2.142:9900");
urls.add("http://127.0.0.1:9200");
// urls.add("http://10.37.2.144:9900");
factory.setHttpClientConfig(new HttpClientConfig
.Builder(urls)//集羣中全部的節點地址
.multiThreaded(true)//是否使用多線程
.defaultMaxTotalConnectionPerRoute(2)//每一個路由最大鏈接數
.maxTotalConnection(20)//整個應用最大的鏈接數
.readTimeout(30000)//超時時間
.build());
JestClient client = factory.getObject();
複製代碼
在應用中能夠經過spring對client進行管理,在應用關閉時須要調用client.shutdownClient();將資源進行釋放
Settings.Builder settingsBuilder = Settings.builder();
settingsBuilder.put("number_of_shards",5);//主分片數
settingsBuilder.put("number_of_replicas",1);//副本數
jestClient.execute(new CreateIndex.Builder("index").settings(settingsBuilder.build().getAsMap()).build());
//建立映射-mapping
PutMapping putMapping = new PutMapping.Builder(
"my_index",
"my_type",
"{ \"my_type\" : { \"properties\" : { \"message\" : {\"type\" : \"string\", \"store\" : \"yes\"} } } }"
).build();
client.execute(putMapping);
複製代碼
ES默認是容許動態建立的,因此在建立index時能夠不用建立類型的mapping,而後存儲document時會動態的建立mapping,查詢index下全部類型的mapping
GET 127.0.0.1:9200/db1/_mapping
刪除index
jestClient.execute(new DeleteIndex.Builder(index)
.build());
複製代碼
增長document
document的增長是比較簡單的
String source = "{\"user\":\"kimchy\"}";//使用接送字符串
String source = jsonBuilder()
.startObject()
.field("user", "kimchy")
.field("postDate", "date")
.field("message", "trying out Elastic Search")
.endObject().string();//使用構造的json
Map<String, String> source = new LinkedHashMap<String,String>();//使用map
source.put("user", "kimchy");
Article source = new Article();//使用pojo對象
source.setAuthor("John Ronald Reuel Tolkien");
source.setContent("The Lord of the Rings is an epic high fantasy novel");
Index index = new Index.Builder(source)
.index("twitter")//指定index
.type("tweet")//指定type
.id("1")//指定id,能夠不指定則ES自動生成id
.build();
jestClient.execute(index);
複製代碼
以上是單個增長,咱們一樣可使用Bulk批量的插入ES:
List<Index> indexList = new ArrayList<>();
for (OrderDto t : datas) {
Index indexDoc = new Index.Builder(t).index(index).type(type).build();
indexList.add(indexDoc);
Bulk.Builder bulkBuilder = new Bulk.Builder();
bulkBuilder.addAction(indexList);
BulkResult br = jestClient.execute(bulkBuilder.build());
}
複製代碼
刪除document
每一個document都是由index,type,id三者共同惟一肯定的,因此能夠指定刪除某個document:
jestClient.execute(new Delete.Builder("1")//id =1
.index("index")// index = index
.type("type")// type = type
.build());
複製代碼
一樣的咱們能夠根據條件進行刪除:
String query ="\"{\n"+
"\"query\": {\n"+
"\"match_all\": {}\n"+
"}\"";//查詢條件
DeleteByQuery deleteByQuery = new DeleteByQuery.Builder(query).build();
JestResult deleteResult = jestClient.execute(deleteByQuery);
複製代碼
如上,表示刪除全部的document,查詢的條件後面會介紹。
一切都是爲了檢索
檢索纔是ES的最誘人的特性,首先先簡單感覺一下
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder memberTerm = QueryBuilders.termQuery("memberId", memberId);//等值查詢
Integer[] channels = {101, 106};
TermsQueryBuilder orderChannelTerm = QueryBuilders.termsQuery("orderChannel", channels);//in查詢
Integer[] activeType = {0, 8, 9, 7};
TermsQueryBuilder activeTypeTerm = QueryBuilders.termsQuery("activeType", activeType);
AggregationBuilder orderItemIdAgg = .field("b2corditemid").size(Integer.MAX_VALUE);
Date now = new Date();
Calendar calendar = Calendar.getInstance(); //獲得日曆
calendar.setTime(now);//把當前時間賦給日曆
calendar.add(calendar.MONTH, -3); //設置爲前3月
Date dBefore = calendar.getTime(); //獲得前3月的時間
RangeQueryBuilder payTimeRange = QueryBuilders.rangeQuery("payTime").gt(dBefore).lt(now);//範圍查詢
searchSourceBuilder.query(QueryBuilders.boolQuery()
.must(memberTerm)// and查詢
.filter(orderChannelTerm)//
.filter(activeTypeTerm)
.filter(payTimeRange)
);
Sort placeTimeSort = new Sort("placeTime", Sort.Sorting.DESC);
Sort idSort = new Sort("orderId", Sort.Sorting.ASC);
searchSourceBuilder.aggregation(orderItemIdAgg);// group by 分組
searchSourceBuilder.from(0).size(20);
Search search = new Search.Builder(searchSourceBuilder.toString())
.addType(type)
.addIndex(index)
.addSort(placeTimeSort)//結果排序
.addSort(idSort)
.build();
複製代碼
如上的查詢能夠相似於sql:
SELECT
*
FROM
bm_client_order_detail o
WHERE
o.`payTime` >= DATE_SUB(NOW(), INTERVAL 3 MONTH)
AND o.memberId = 101204389
AND o.orderChannel IN (101, 106)
AND activeType IN (0, 8, 9, 17)
GROUP BY
o.b2corditemid
ORDER BY
o.placeTime DESC,
o.id ASC
LIMIT 0,20
複製代碼
未完待續!!!