ElasticSearch(5.5.2)在java中的使用
ElasticSearch版本:5.5.2
jdk版本:1.8+
Elasticsearch基本內容:
叢集(Cluster): ES是一個分散式的搜尋引擎,一般由多臺物理機組成。這些物理機,通過配置一個相同的cluster name,互相發現,把自己組織成一個叢集。
節點(Node):同一個叢集中的一個Elasticearch主機。
Node型別:
1)data node: 儲存index資料。
2)client node: 不儲存index,處理客戶端請求。
3)master node: 不儲存index,叢集管理,如管理路由資訊(routing infomation),判斷node是否available,當有node出現或消失時重定位分片(shards),當有node failure時協調恢復。(所有的master node會選舉出一個master leader node)
主分片(Primary shard):索引(下文介紹)的一個物理子集。同一個索引在物理上可以切多個分片,分佈到不同的節點上。分片的實現是Lucene 中的索引。
注意:ES中一個索引的分片個數是建立索引時就要指定的,建立後不可再改變。所以開始建一個索引時,就要預計資料規模,將分片的個數分配在一個合理的範圍。
副本分片(Replica shard):每個主分片可以有一個或者多個副本,個數是使用者自己配置的。ES會盡量將同一索引的不同分片分佈到不同的節點上,提高容錯性。對一個索引,只要不是所有shards所在的機器都掛了,就還能用。
索引(Index):邏輯概念,一個可檢索的文件物件的集合。類似與DB中的database概念。同一個叢集中可建立多個索引。比如,生產環境常見的一種方法,對每個月產生的資料建索引,以保證單個索引的量級可控。
型別(Type):索引的下一級概念,大概相當於資料庫中的table。同一個索引裡可以包含多個 Type。
文件(Document):即搜尋引擎中的文件概念,也是ES中一個可以被檢索的基本單位,相當於資料庫中的row,一條記錄。
欄位(Field):相當於資料庫中的column。ES中,每個文件,其實是以json形式儲存的。而一個文件可以被視為多個欄位的集合。比如一篇文章,可能包括了主題、摘要、正文、作者、時間等資訊,每個資訊都是一個欄位,最後被整合成一個json串,落地到磁碟。
對映(Mapping):相當於資料庫中的schema,用來約束欄位的型別,不過 Elasticsearch 的 mapping 可以不顯示地指定、自動根據文件資料建立。
Elasticsearch叢集可以包含多個索引(indices),每一個索引可以包含多個型別(types),每一個型別包含多個文件(documents),然後每個文件包含多個欄位(Fields)
1.在idea中建立maven專案,匯入maven依賴
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>1.8</compilerVersion>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2.1 在src目錄下的test目錄下新建ElasticsearchTest類
2.2 先定義基本常量,方便後面的使用。
public final static String HOST = "127.0.0.1"; //本地伺服器部署
public final static int PORT = 9300; //http請求的埠是9200,客戶端是9300
private TransportClient client = null; 客戶端連線
2.3 新增@Before註解,指定測試程式開始前使用的client
@SuppressWarnings({ "resource", "unchecked" })
@Before
public void getConnect() throws UnknownHostException {
client = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddresses(
new InetSocketTransportAddress(InetAddress.getByName(HOST),PORT));
System.out.println("連線資訊:" + client.toString());
}
2.4 新增@After註解,測試程式執行後關閉client連線
@After
public void closeConnect() {
if(null != client) {
System.out.println("執行關閉連線操作...");
client.close();
}
}
2.5 建立索引(XContentBuilder)
@Test
public void addIndex() throws IOException {
System.out.println("測試中");
/*
*建立文件物件
* 引數一blog1:表示索引物件
* 引數二article:型別
* 引數三1:建立id
*/
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.field("id", 1)
.field("title", "elasticSearch搜尋引擎")
.field("content",
"全球搜尋伺服器")
.endObject();
IndexResponse indexResponse = client.prepareIndex("blog1", "article",Integer.toString(1)).setSource(builder).get();
}
// 結果獲取
String index = indexResponse.getIndex()
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
RestStatus status = indexResponse.status();
System.out.println("index索引:"+index + "--型別:" + type + "--索引id:" + id + "--版本:" + version + "--狀態:" + status);
}
2.5.2 建立索引(json)
@Test
public void addIndex() throws IOException {
System.out.println("測試中");
String json = "{" +
"\"name\":\"深入淺出Node.js\"," +
"\"author\":\"樸靈 \"," +
"\"pubinfo\":\"人民郵電出版社 \"," +
"\"pubtime\":\"2013-12-1 \"," +
"\"desc\":\"本書從不同的視角介紹了 Node 內在的特點和結構。由首章Node 介紹為索引,涉及Node 的各個方面,主要內容包含模組機制的揭示、非同步I/O 實現原理的展現、非同步程式設計的探討、記憶體控制的介紹、二進位制資料Buffer 的細節、Node 中的網路程式設計基礎、Node 中的Web 開發、程序間的訊息傳遞、Node 測試以及通過Node 構建產品需要的注意事項。最後的附錄介紹了Node 的安裝、除錯、編碼規範和NPM 倉庫等事宜。本書適合想深入瞭解 Node 的人員閱讀。\"" +
"}";
IndexResponse indexResponse = client.prepareIndex("blog2","goods").setSource(json).get();
// 結果獲取
String index = indexResponse.getIndex()
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
RestStatus status = indexResponse.status();
System.out.println("index索引:"+index + "--型別:" + type + "--索引id:" + id + "--版本:" + version + "--狀態:" + status);
}
2.5.3 建立索引(map)
@Test
public void addIndex() throws IOException {
System.out.println("測試中");
Map<String, Object> map = new HashMap<String, Object>();
map.put("name","Go Web程式設計");
map.put("author","謝孟軍 ");
map.put("pubinfo","電子工業出版社");
map.put("pubtime","2013-6");
map.put("desc","《Go Web程式設計》介紹如何使用Go語言編寫Web,包含了Go語言的入門、Web相關的一些知識、Go中如何處理Web的各方面設計(表單、session、cookie等)、資料庫以及如何編寫GoWeb應用等相關知識。通過《Go Web程式設計》的學習能夠讓讀者瞭解Go的執行機制,如何用Go編寫Web應用,以及Go的應用程式的部署和維護等,讓讀者對整個的Go的開發瞭如指掌。");
IndexResponse indexResponse = client.prepareIndex("blog2", "goods").setSource(map).execute().actionGet();
// 結果獲取
String index = indexResponse.getIndex()
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
RestStatus status = indexResponse.status();
System.out.println("index索引:"+index + "--型別:" + type + "--索引id:" + id + "--版本:" + version + "--狀態:" + status);
}
2.6 刪除索引
@Test
public void deleteByObject() throws Exception {
client.delete(new DeleteRequest("blog1", "article", Integer.toString(1)).get();
}
2.7 獲取文件資訊@Test
public void getIndexNoMapping() throws Exception {
GetResponse actionGet = client.prepareGet("blog1", "article", "1").execute().actionGet();
System.out.println(actionGet.getSourceAsString());
}
2.8 查詢所有文件資訊
@Test
public void getMatchAll() throws IOException {
// get() === execute().actionGet()
SearchResponse searchResponse = client.prepareSearch("blog1")
.setTypes("article").setQuery(QueryBuilders.matchAllQuery())
.get();
// 獲取命中次數,查詢結果有多少物件
SearchHits hits = searchResponse.getHits();
System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()) {
// 每個查詢物件
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString()); // 獲取字串格式列印
System.out.println("title:" + searchHit.getSource().get("title"));
}
}
2.9 關鍵字查詢
@Test
public void getKeyWord() throws IOException {
long time1 = System.currentTimeMillis();
SearchResponse searchResponse = client.prepareSearch("blog1")
.setTypes("article").setQuery(QueryBuilders.queryStringQuery("你們"))
.get();
// 獲取命中次數,查詢結果有多少物件
SearchHits hits = searchResponse.getHits();
System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()) {
// 每個查詢物件
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString()); // 獲取字串格式列印
System.out.println("title:" + searchHit.getSource().get("title"));
}
long time2 = System.currentTimeMillis();
System.out.println("花費"+(time2-time1)+"毫秒");
}
2.10 萬用字元,詞條查詢
“*”表示0到 多個字元,“?”表示一個字元
@Test
public void getByLike() throws IOException {
long time1 = System.currentTimeMillis();
SearchResponse searchResponse = TransportTemplate.getClient().prepareSearch("blog1")
.setTypes("article").setQuery(QueryBuilders.wildcardQuery("desc","可愛*")) //萬用字元查詢
// .setTypes("article").setQuery(QueryBuilders.wildcardQuery("content","伺服器"))
// .setTypes("article").setQuery(QueryBuilders.termQuery("content","全文")) //詞條查詢
//一般情況下只顯示十條資料
//from + size must be less than or equal to: [10000]
//Scroll Search->支援1萬以上的資料量
// .setSize(10000)
.get();
// 獲取命中次數,查詢結果有多少物件
SearchHits hits = searchResponse.getHits();
System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()) {
// 每個查詢物件
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString()); // 獲取字串格式列印
System.out.println("title:" + searchHit.getSource().get("title"));
}
long time2 = System.currentTimeMillis();
System.out.println("花費"+(time2-time1)+"毫秒");
}
2.11 組合查詢
下面的.must()方法這個位置,一般常用的有.must(), .should(), mustNot()這三種方法,表示交集,並集,不一定。
@Test
public void combinationQuery() throws Exception{
SearchResponse searchResponse = client.prepareSearch("blog1").setTypes("article")
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title", "搜尋"))// 詞條查詢
//.must(QueryBuilders.rangeQuery("id").from(1).to(5)) // 範圍查詢
//因為IK分詞器,在儲存的時候將英文都變成了小寫
.must(QueryBuilders.wildcardQuery("content", "Rest*".toLowerCase())) // 模糊查詢
.must(QueryBuilders.queryStringQuery( "服電風扇豐盛的分器")) // 關鍵字(含有)
)
.get();
SearchHits hits = searchResponse.getHits();
System.out.println("總記錄數:"+hits.getTotalHits());
Iterator<SearchHit> iterator = hits.iterator();
while(iterator.hasNext()){
SearchHit searchHit = iterator.next();
System.out.println(searchHit.getSourceAsString());
Map<String, Object> source = searchHit.getSource();
// System.out.println(source.get("id")+" "+source.get("title")+" "+source.get("content"));
}
}