1. 程式人生 > >ElasticSearch(5.5.2)在java中的使用

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"));
        }

    }