Elasticsearch

1 Elasticsearch

1.1 Elasticsearch

1.1.1 Concepts

文檔(Document):索引和搜索時使用的主要數據載體,包含一個或多個存有數據的字段。

字段(Field):文檔的一部分,包含名稱和值兩部分。

詞(Term):一個搜索單元,表示文本中的一個詞。

索引(Index):文檔的集合。

類型(Type):索引下一類文檔的集合。

1.1.2 Elasticsearch install

Windows環境

官網下載zip版本的Elasticsearch:https://www.elastic.co/cn/downloads/elasticsearch

       第一步,下載並解壓。

       第二步,進入Elasticsearch目錄,運行:

cd E:\Develop\elasticsearch-5.6.3

bin\elasticsearch.bat

第三步,測試:

curl -XGET "http://localhost:9200/"

       如果沒有curl,可以從https://curl.haxx.se/download.html下載安裝。或者直接瀏覽器訪問http://localhost:9200/

Linux環境

官網下載tar.gz版本的Elasticsearch:https://www.elastic.co/cn/downloads/elasticsearch,並上傳至/opt目錄。

第一步,root用戶登錄,解壓。因爲Elasticsearch不允許使用root用戶啓動,所以還需要添加elastic用戶,並改變目錄的owner:

tar xzvf elasticsearch-5.6.3.tar.gz

adduser elastic

passwd elastic

chown -R elastic /opt/elasticsearch-5.6.3

       第二步,切換到elastic用戶運行:

su elastic

cd elasticsearch-5.6.3

bin/elasticsearch

       第三步,測試:

curl -XGET "http://localhost:9200/"

       實際過程中,可能出現以下問題。

       1、9200端口無法在其他機器上訪問。

解決辦法是修改conf/elasticsearch.yml,添加:

network.host: 0.0.0.0

       2、啓動時報如下錯:

[1]:max file descriptors [4096] for elasticsearch process is too low, increase toat least [65536]

[2]:max virtual memory areas vm.max_map_count [65530] is too low, increase to atleast [262144]

       解決辦法是:

       vi /etc/security/limits.conf,添加:

* hard nofile 65536

* soft nofile 65536

       vi /etc/sysctl.conf,添加:

vm.max_map_count=655360

  執行

sysctl -p

   全部修改完成後,重新登錄elastic用戶並啓動elasticsearch即可。

       注意:如無特殊說明,後續內容默認使用Linux作爲安裝環境。

1.1.3 Elasticsearch Cluster

本例中規劃了3臺服務器,分別爲cs4:192.168.159.104、cs5:192.168.159.105、cs6:192.168.159.106。其中cs4作爲master node和data node,cs5、cs6作爲data node。

第一步,分別在三臺服務器上單機安裝Elasticsearch。

第二步,分別配置cs4的/opt/elasticsearch-5.6.3/config/elasticsearch.yml。cs4爲:

cluster.name: cluster-demo

node.name: node-cs4

network.host: 0.0.0.0

http.port: 9200

 

http.cors.enabled: true

http.cors.allow-origin: "*"

 

node.master: true

node.data: true

discovery.zen.ping.unicast.hosts: ["192.168.159.104"]

       cs5爲:

cluster.name: cluster-demo

node.name: node-cs5

network.host: 0.0.0.0

http.port: 9200

 

http.cors.enabled: true

http.cors.allow-origin: "*"

 

node.master: false

node.data: true

discovery.zen.ping.unicast.hosts: ["192.168.159.104"]

cs6爲:

cluster.name: cluster-demo

node.name: node-cs6

network.host: 0.0.0.0

http.port: 9200

 

http.cors.enabled: true

http.cors.allow-origin: "*"

 

node.master: false

node.data: true

discovery.zen.ping.unicast.hosts: ["192.168.159.104"]

第三步,先以elastic用戶啓動cs4的Elasticsearch,啓動成功後啓動cs5、cs6上的Elasticsearch。當在cs5、cs6控制檯看到如下輸出,說明集羣識別成功。

       該示例中指定了cluster.name=cluster-demo,後面使用API連接時需要使用該名稱。通過head插件也可以查看集羣情況。

 

1.1.4 Elasticsearch Plugin

1.1.4.1 elasticsearch-head

elasticsearch-head是一個與ElasticsearchCluster交互的前端工具。

對於Elasticsearch 2.X,直接執行命令安裝:

elasticsearch/bin/plugin install mobz/elasticsearch-head。

對於Elasticsearch 5.X,需要單獨安裝,步驟如下:

第一步,安裝git:

yum -y install git

第二步,安裝nodejs。

可以使用的Linux 系統 (x86/x64)下已編譯好的版本https://npm.taobao.org/mirrors/node/v8.7.0/node-v8.7.0-linux-x64.tar.xz

tar xvf node-v8.7.0-linux-x64.tar.xz

cd node-v8.7.0-linux-x64/

ln -s /opt/node-v8.7.0-linux-x64/bin/node /usr/local/bin/node

ln -s /opt/node-v8.7.0-linux-x64/bin/npm /usr/local/bin/npm

       也可以使用以下簡單方式安裝:

curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash -

yum install nodejs

查看node安裝情況,並設置國內鏡像:

node -v

npm config set registry https://registry.npm.taobao.org

第三步,下載,構建並啓動:

git clone git://github.com/mobz/elasticsearch-head.git

cd elasticsearch-head

npm install

npm run start

訪問http://localhost:9100/,看看能否成功連接到Elasticsearch。

如果無法成功連接,則嘗試修改conf/elasticsearch.yml,在末尾添加:

http.cors.enabled: true

http.cors.allow-origin: "*"

       然後重啓Elasticsearch,並重試。

 

1.1.4.2 elasticsearch-analysis-ik

https://github.com/medcl/elasticsearch-analysis-ik/releases/下載zip並解壓到your-es-root/plugins/,重啓Elasticsearch。

訪問http://cs4:9200/demo/_analyze?analyzer=ik_smart&text=我們都是中國人&pretty,查看分詞測試結果。

       重新設置demo索引(其中content是本例中的一個Field):

curl -XPUT http://cs4:9200/demo -d '{
   
"settings" : {
        "analysis" : {
            "analyzer" : {
                "ik" : {
                    "tokenizer" : "ik_smart"
                }
            }
        }
    },
    "mappings" : {
        "news" : {
            "dynamic" : true,
            "properties" : {
                "content" : {
                    "type" : "string",
                    "analyzer" : "ik_smart"
                }
            }
        }
    }
}'

       執行搜索:

curl -XPOST http://cs4:9200/demo/news/_search -d '{
   
"query" : { "term" : { "content" : "企業" }},
   
"highlight" : {
        "pre_tags" : [""],
        "post_tags" : [""],
        "fields" : {
            "subject" : {}
        }
    }
}'

 

1.1.5 Elasticsearch Restful API

ElasticSearch採用REST API,所有的操作都可通過Http API完成交互,例如增刪改查、別名配置。

1.1.5.1 Document APIs

1.1.5.1.1             Index API

用於將JSON文檔添加或更新到一個指定的索引。

下面例子將JSON文檔添加到了index=twitter下的type=tweet中,並指定文檔id=1:

PUT twitter/tweet/1
{
   
"user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

默認情況下(action.auto_create_index=true),如果指定的index及type沒有創建的話,系統會自動創建這個index以及type mapping。

上面的請求可以接受一個op_type=create參數用來強制創建一個index,若index已存在則失敗。

上面的請求也可以不指定文檔id,此時系統會自動生成一個id,此時自動會有op_type=create。

 

1.1.5.1.2             Get API

用於從index中根據id獲取文檔。

GET twitter/tweet/1

       此API也允許使用HEAD來檢測一個文檔是否存在:

HEAD twitter/tweet/1

1.1.5.1.3             Delete API

用於從index中根據id刪除文檔。

DELETE twitter/tweet/1

1.1.5.1.4             Delete By Query API

用於從index中根據查詢的結果刪除文檔。

POST twitter/_delete_by_query
{
 
"query": {
    "match": {
      "message": "some message"
    }
  }
}

1.1.5.1.5             Update API

用於修改index中的文檔。

POST test/type1/1/_update
{
   
"script" : "ctx._source.new_field = 'value_of_new_field'"
}

或:

POST test/type1/1/_update
{
   
"doc" : {
        "name" : "new_name"
    }
}

doc 參數,它只是與現有的文檔進行合併。對象被合併到一起,覆蓋現有的字段,增加新的字段

1.1.5.1.6             Update By Query API

用於從index中根據查詢的結果修改文檔。

POST twitter/_update_by_query
{
 
"script": {
    "source": "ctx._source.likes++",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}

1.1.5.1.7             Bulk API

用於批量執行文檔操作。下例發送了index、delete、create、update四個請求。

POST _bulk
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "type1", "_id" : "2" } }
{ "create" : { "_index" : "test", "_type" : "type1", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

1.1.5.1.8             Reindex API

用於將文檔從一個index拷貝到另一個index。

POST _reindex
{
 
"source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}

1.1.5.2 Search APIs

1.1.5.1.9             URI Search

將請求參數放入URI中。

GET twitter/tweet/_search?q=user:kimchy&analyzer=simple

GET demo/_search?q=content:中國共產黨特色&analyzer=ik

 

1.1.5.3.1             Request Body Search

將請求參數放入Body中。

GET /_search
{
   
"from" : 0, "size" : 10,
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

1.1.5.3.2             Count API

獲取匹配查詢的文檔數量。

GET /twitter/tweet/_count?q=user:kimchy
GET /twitter/tweet/_count
{
   
"query" : {
        "term" : { "user" : "kimchy" }
    }
}

1.1.5.3 Indices APIs

1.1.5.3.1             Create Index

創建索引,可以設置settings、mappings等值。

PUT demo
{
   
"settings" : {
        "number_of_shards" : 3,
        "number_of_replicas" : 2,
        "analysis" : {
            "analyzer" : {
                "ik" : {
                    "tokenizer" : "ik_smart"
                }
            }
        }
    },
    "mappings" : {
        "news" : {
            "dynamic" : true,
            "properties" : {
                "content" : {
                    "type" : "string",
                    "analyzer" : "ik_smart"
                }
            }
        }
    }
}

1.1.5.3.2             Delete Index

刪除索引。

DELETE /twitter

1.1.5.3.3             Get Index

查看索引。

GET /twitter

HEAD /twitter

1.1.5.3.4             Open/Close Index

開啓、關閉索引。

POST /my_index/_close
POST /my_index/_open

1.1.5.3.5             Put Mapping

設置mappings。

PUT twitter
{
 
"mappings": {
    "tweet": {
      "properties": {
        "message": {
          "type": "text"
        }
      }
    }
  }
}

PUT twitter/_mapping/user
{
  "properties": {
    "name": {
      "type": "text"
    }
  }
}

PUT twitter/_mapping/tweet
{
  "properties": {
    "user_name": {
      "type": "text"
    }
  }
}

1.1.5.3.6             Get Mapping

獲取mappings。

GET /twitter/_mapping/tweet

1.1.5.3.7             Update Indices Settings

更新settings。

POST /twitter/_close

PUT /twitter/_settings
{
 
"analysis" : {
    "analyzer":{
      "content":{
        "type":"custom",
        "tokenizer":"whitespace"
      }
    }
  }
}

POST /twitter/_open

1.1.5.3.8             Get Settings

查看settings。

GET /twitter/_settings

1.1.5.4 Cat APIs

接口

含義

/_cat/allocation

查看分配資源

/_cat/shards

查看分片信息

/_cat/shards/{index}

查看分片信息

/_cat/master

查看master節點信息

/_cat/nodes

查看節點信息

/_cat/tasks

查看任務信息

/_cat/indices

查詢索引信息

/_cat/indices/{index}

查詢索引信息

/_cat/segments

查看分段信息

/_cat/segments/{index}

查看分段信息

/_cat/count

查看文檔個數

/_cat/count/{index}

查看文檔個數

/_cat/recovery

查看恢復信息

/_cat/recovery/{index}

查看恢復信息

/_cat/health

查看健康信息

/_cat/pending_tasks

查看掛起任務信息

/_cat/aliases

查看索引別名

/_cat/aliases/{alias}

查看索引別名

/_cat/thread_pool

查看線程池信息

/_cat/thread_pool/{thread_pools}

查看線程池信息

/_cat/plugins

查看插件信息

/_cat/fielddata

查看字段分配信息

/_cat/fielddata/{fields}

查看字段分配信息

1.1.5.5 Cluster APIs

接口

含義

_cluster/health

查看集羣健康狀態

_cluster/state

查看集羣狀態

_cluster/stats

查看集羣統計信息

1.1.6 Java API

下面以Spring Boot工程環境講解,在此之前,需要參照《elasticsearch-analysis-ik》一節內容設置好IK中文分詞插件。

1.1.6.1 Elasticsearch 5.x + API

第一步,新建項目,並引入elasticsearch、log4j、fastjson等依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
  
<modelVersion>4.0.0</modelVersion>
  
<groupId>com.example</groupId>
  
<artifactId>spring-data-elasticsearch</artifactId>
  
<version>0.0.1-SNAPSHOT</version>
  
<packaging>jar</packaging>
  
<name>spring-data-elasticsearch</name>
  
<description></description>

  
<parent>
     
<groupId>org.springframework.boot</groupId>
     
<artifactId>spring-boot-starter-parent</artifactId>
     
<version>1.5.8.RELEASE</version>
     
<relativePath/> <!-- lookup parent from repository -->
  
</parent>

  
<properties>
     
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     
<java.version>1.8</java.version>
  
</properties>

  
<dependencies>
       
<dependency>
           
<groupId>org.springframework.boot</groupId>
           
<artifactId>spring-boot-starter-web</artifactId>
       
</dependency>
       
<dependency>
           
<groupId>org.elasticsearch</groupId>
           
<artifactId>elasticsearch</artifactId>
        
   <version>5.6.3</version>
       
</dependency>
       
<dependency>
           
<groupId>org.elasticsearch.client</groupId>
           
<artifactId>transport</artifactId>
           
<version>5.6.3</version>
       
</dependency>
       
<dependency>
           
<groupId>org.apache.logging.log4j</groupId>
           
<artifactId>log4j-core</artifactId>
           
<version>2.9.1</version>
       
</dependency>
       
<dependency>
           
<groupId>com.alibaba</groupId>
           
<artifactId>fastjson</artifactId>
           
<version>1.2.39</version>
       
</dependency>

     
<dependency>
        
<groupId>org.springframework.boot</groupId>
        
<artifactId>spring-boot-starter-test</artifactId>
        
<scope>test</scope>
     
</dependency>
  
</dependencies>

  
<build>
     
<plugins>
        
<plugin>
           
<groupId>org.springframework.boot</groupId>
           
<artifactId>spring-boot-maven-plugin</artifactId>
        
</plugin>
     
</plugins>
  
</build>
</
project>

       第二步,編寫配置類,負責提供Elasticsearch客戶端工具Client的實例:

@Configuration
public class ElasticsearchConfig {
   
@Bean
   
public Client client() throws Exception {
       
Settings settings = Settings.builder()
                .put("cluster.name", "elasticsearch")
               
.put("client.transport.sniff", true)
               
.build();
        TransportClient client = new PreBuiltTransportClient(settings)
               
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.159.104"), 9300))
               
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.159.105"), 9300))
               
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.159.106"), 9300));
       
return client;
   
}
}

       第三步,編寫新聞實體類:

public class News {
   
private String id;
   
private String title;
   
private String content;

   
public News() {
   
}

    public News(String id, String title, String content) {
       
this.id = id;
       
this.title = title;
       
this.content = content;
   
}
    // getters and setters
   
@Override
   
public String toString() {
       
return "News{" +
               
"id='" + id + '\'' +
               
", title='" + title + '\'' +
               
", content='" + content + '\'' +
               
'}';
   
}
}

       第四步,編寫測試類。注入Client實例,並使用其完成對索引、文檔的操作:

package com.example.demo;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.News;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.delete.DeleteRequestBuilder;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
import java.util.UUID;

@RunWith(SpringRunner.class)
@SpringBootTest
public class EsApiTests {
   
@Autowired
   
private Client client;
   
private static final String[] contents = new String[]{
           
"18日,中國共產黨第十九次全國代表大會在北京隆重召開,習近平代表第十八屆中央委員會向大會作報告。以下爲新華網直播全文實錄:",
           
"同志們:現在,我代表第十八屆中央委員會向大會作報告。", "中國共產黨第十九次全國代表大會,是在全面建成小康社會決勝階段、中國特色社會主義進入新時代的關鍵時期召開的一次十分重要的大會。",
           
"大會的主題是:不忘初心,牢記使命,高舉中國特色社會主義偉大旗幟,決勝全面建成小康社會,奪取新時代中國特色社會主義偉大勝利,爲實現中華民族偉大復興的中國夢不懈奮鬥。",
           
"不忘初心,方得始終。中國共產黨人的初心和使命,就是爲中國人民謀幸福,爲中華民族謀復興。這個初心和使命是激勵中國共產黨人不斷前進的根本動力。全黨同志一定要永遠與人民同呼吸、共命運、心連心,永遠把人民對美好生活的嚮往作爲奮鬥目標,以永不懈怠的精神狀態和一往無前的奮鬥姿態,繼續朝着實現中華民族偉大復興的宏偉目標奮勇前進。"};

   
// 創建索引
   
@Test
   
public void createIndex() {
       
CreateIndexRequestBuilder builder = client.admin().indices().prepareCreate("demo");
       
CreateIndexResponse response = builder.get();
        System.out.println(response.index());
   
}

    // 刪除索引
   
@Test
   
public void deleteIndex() {
       
DeleteIndexRequestBuilder builder = client.admin().indices().prepareDelete("demo");
       
DeleteIndexResponse response = builder.get();
        System.out.println(response.isAcknowledged());
   
}

    // 檢測索引
   
@Test
   
public void existsIndex() {
       
IndicesExistsRequestBuilder builder = client.admin().indices().prepareExists("demo");
       
IndicesExistsResponse response = builder.execute().actionGet();
        System.out.println(response.isExists());
   
}

    // 刪除類型
   
@Test
   
public void deleteType() {
       
DeleteRequestBuilder builder = client.prepareDelete().setIndex("demo").setType("news");
       
DeleteResponse response = builder.execute().actionGet();
        System.out.println(response);
   
}

    // 索引文檔
   
@Test
   
public void indexDoc() {
       
for (int i = 0; i < contents.length; i++) {
           
News news = new News(UUID.randomUUID().toString(), "十九大", contents[i]);
           
String json = JSONObject.toJSONString(news);
            IndexRequestBuilder builder = client.prepareIndex("demo", "news").setSource(json, XContentType.JSON);
           
IndexResponse response = builder.execute().actionGet();
            System.out.println(response);
       
}
    }

    //刪除文檔
   
@Test
   
public void deleteDoc() {
       
DeleteRequestBuilder builder = client.prepareDelete("demo", "news", "AV-FzCCY9O97GAKX9QZm");
       
DeleteResponse response = builder.execute().actionGet();
        System.out.println(response);
   
}

    // 更新文檔
   
@Test
   
public void updateDoc() {
       
// 先查詢
       
GetRequestBuilder getBuilder = client.prepareGet("demo", "news", "AV-FzCAz9O97GAKX9QZl");
       
GetResponse getResponse = getBuilder.execute().actionGet();
        Map<String, Object> news = getResponse.getSource();
        // 再更新
       
news.put("title", news.get("title") + "_updated");
       
UpdateRequestBuilder builder = client.prepareUpdate("demo", "news", "AV-FzCAz9O97GAKX9QZl")
               
.setDoc(news);
        UpdateResponse response = builder.execute().actionGet();
        System.out.println(response);
   
}

    // 獲取文檔
  
 
@Test
   
public void getDoc() {
       
GetRequestBuilder builder = client.prepareGet("demo", "news", "AV-FzCAz9O97GAKX9QZl");
       
GetResponse response = builder.execute().actionGet();
        System.out.println(response.getSourceAsString());
   
}

    // 搜索文檔:詞條查詢(不分詞,整體匹配)
   
@Test
   
public void termQuery() {
       
QueryBuilder queryBuilder = QueryBuilders.termQuery("content", "中國");
       
doQuery(queryBuilder);
    }

    // 搜索文檔:匹配查詢(分詞)
   
@Test
   
public void matchQuery() {
       
QueryBuilder queryBuilder = QueryBuilders.matchQuery("content", "中國特色社會主義");
       
doQuery(queryBuilder);
    }

    // 搜索文檔:多屬性匹配查詢(分詞)
   
@Test
   
public void multiMatchQuery() {
       
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("中國特色社會主義", "title", "content");
       
doQuery(queryBuilder);
    }

    // 搜索文檔:所有文檔
   
@Test
   
public void matchAllQuery() {
       
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        doQuery(queryBuilder);
    }

    // 搜索文檔:布爾查詢,多條件組合
   
@Test
   
public void boolQuery() {
       
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("content", "中國"))
               
.should(QueryBuilders.matchQuery("content", "中國特色社會主義"));
       
doQuery(queryBuilder);
    }

    // 執行搜索
   
private void doQuery(QueryBuilder queryBuilder) {
       
SearchRequestBuilder builder = client.prepareSearch("demo")
               
.setTypes("news")
               
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
               
.setQuery(queryBuilder)
                .setFrom(0).setSize(60).setExplain(true);
       
SearchResponse response = builder.get();
        SearchHits hits = response.getHits();
        hits.forEach(hit -> {
            System.out.println(hit.getSourceAsString());
       
});
    }
}

 

1.1.6.2 Elasticsearch 2.x + Spring Data Elasticsearch

Spring Data操作Elasticsearch的方式就像是Hibernate操作關係型數據庫。目前的spring-boot-starter-data-elasticsearch1.5.8/spring-data-elasticsearch-2.1.8支持的Elasticsearch版本爲2.4.6,對Elasticsearch5的支持還不穩定。

第一步,新建項目,並引入spring-boot-starter-data-elasticsearch依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
   
<modelVersion>4.0.0</modelVersion>
   
<groupId>com.example</groupId>
   
<artifactId>spring-data-elasticsearch</artifactId>
   
<version>0.0.1-SNAPSHOT</version>
   
<packaging>jar</packaging>
   
<name>spring-data-elasticsearch</name>
   
<description></description>

   
<parent>
       
<groupId>org.springframework.boot</groupId>
       
<artifactId>spring-boot-starter-parent</artifactId>
       
<version>1.5.8.RELEASE</version>
       
<relativePath/> <!-- lookup parent from repository -->
   
</parent>

   
<properties>
       
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
       
<java.version>1.8</java.version>
   
</properties>

   
<dependencies>
       
<dependency>
           
<groupId>org.springframework.boot</groupId>
           
<artifactId>spring-boot-starter-web</artifactId>
       
</dependency>
       
<dependency>
           
<groupId>org.springframework.boot</groupId>
           
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
       
</dependency>
        <dependency>
           
<groupId>org.springframework.boot</groupId>
           
<artifactId>spring-boot-starter-test</artifactId>
           
<scope>test</scope>
       
</dependency>
   
</dependencies>

   
<build>
       
<plugins>
           
<plugin>
               
<groupId>org.springframework.boot</groupId>
               
<artifactId>spring-boot-maven-plugin</artifactId>
           
</plugin>
       
</plugins>
   
</build>
</
project>

       第二步,編寫application.properties,配置elasticsearch:

spring.data.elasticsearch.cluster-nodes=localhost:9300

       第三步,編寫新聞實體類,並加入spring-data-elasticsearch註解:

package com.example.demo.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;

@Document(indexName = "demo", type = "news")
public class News {
   
@Id
   
private String id;
   
@Field
   
private String title;
   
@Field
   
private String content;

   
public News() {
   
}

    public News(String id, String title, String content) {
       
this.id = id;
       
this.title = title;
       
this.content = content;
   
}
    // getters and setters
   
@Override
   
public String toString() {
       
return "News{" +
               
"id='" + id + '\'' +
               
", title='" + title + '\'' +
               
", content='" + content + '\'' +
               
'}';
   
}
}

第四步,編寫Dao類,可以先不擴展自己的方法:

package com.example.demo.repository;
import com.example.demo.entity.News;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface NewsRepository extends ElasticsearchRepository<News, String> {
}

第五步,編寫測試類。注入NewsRepository、ElasticsearchTemplate的實例,並使用其完成對索引、文檔的操作:

package com.example.demo;

import com.example.demo.entity.News;
import com.example.demo.repository.NewsRepository;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SDEsApiTests {
   
@Autowired
   
private NewsRepository newsRepository;
   
@Autowired
   
private ElasticsearchTemplate elasticsearchTemplate;
   
private static final String[] contents = new String[]{
           
"18日,中國共產黨第十九次全國代表大會在北京隆重召開,習近平代表第十八屆中央委員會向大會作報告。以下爲新華網直播全文實錄:",
           
"同志們:現在,我代表第十八屆中央委員會向大會作報告。", "中國共產黨第十九次全國代表大會,是在全面建成小康社會決勝階段、中國特色社會主義進入新時代的關鍵時期召開的一次十分重要的大會。",
           
"大會的主題是:不忘初心,牢記使命,高舉中國特色社會主義偉大旗幟,決勝全面建成小康社會,奪取新時代中國特色社會主義偉大勝利,爲實現中華民族偉大復興的中國夢不懈奮鬥。",
           
"不忘初心,方得始終。中國共產黨人的初心和使命,就是爲中國人民謀幸福,爲中華民族謀復興。這個初心和使命是激勵中國共產黨人不斷前進的根本動力。全黨同志一定要永遠與人民同呼吸、共命運、心連心,永遠把人民對美好生活的嚮往作爲奮鬥目標,以永不懈怠的精神狀態和一往無前的奮鬥姿態,繼續朝着實現中華民族偉大復興的宏偉目標奮勇前進。"};

   
// 創建索引
   
@Test
   
public void createIndex() {
       
elasticsearchTemplate.createIndex(News.class);
       
elasticsearchTemplate.createIndex("demo");
   
}

    // 刪除索引
   
@Test
   
public void deleteIndex() {
       
elasticsearchTemplate.deleteIndex(News.class);
       
elasticsearchTemplate.deleteIndex("demo");
   
}

    // 檢測索引
   
@Test
   
public void existsIndex() {
       
elasticsearchTemplate.indexExists(News.class);
       
elasticsearchTemplate.indexExists("demo");
       
elasticsearchTemplate.typeExists("demo", "news");
   
}

    // 索引文檔
   
@Test
   
public void indexDoc() {
       
for (int i = 0; i < contents.length; i++) {
           
News news = new News(UUID.randomUUID().toString(), "十九大", contents[i]);
           
newsRepository.save(news);
       
}
    }

    //刪除文檔
   
@Test
   
public void deleteDoc() {
       
newsRepository.deleteAll();
       
newsRepository.delete("114ef9cb-f13f-450d-b8d7-a567ee78ae3b");
   
}

    // 獲取文檔
   
@Test
   
public void getDoc() {
       
News news = newsRepository.findOne("114ef9cb-f13f-450d-b8d7-a567ee78ae3b");
       
System.out.println(news);
   
}

    // 搜索文檔:詞條查詢(不分詞,整體匹配)
   
@Test
   
public void termQuery() {
       
SearchQuery searchQuery = new NativeSearchQueryBuilder()
               
.withQuery(QueryBuilders.termQuery("content", "中國特色社會主義"))
               
.build();
        Page<News> page = newsRepository.search(searchQuery);
       
page.forEach(e -> System.out.println(e));
   
}

    // 搜索文檔:匹配查詢(分詞)
   
@Test
   
public void matchQuery() {
       
System.out.println("------------result 1------------");
       
QueryBuilder queryBuilder = QueryBuilders.matchQuery("content", "中國特色社會主義");
       
Page<News> page = newsRepository.search(queryBuilder, new PageRequest(0, 10));// 分頁:第1頁,每頁10
       
page.forEach(e -> System.out.println(e));

       
System.out.println("------------result 2------------");
       
SearchQuery searchQuery = new NativeSearchQueryBuilder()
               
.withQuery(QueryBuilders.matchQuery("content", "中國特色社會主義"))
               
.withPageable(new PageRequest(0, 10)) // 分頁:第1頁,每頁10
               
.build();
       
page = newsRepository.search(searchQuery);
       
page.forEach(e -> System.out.println(e));
   
}

}

 

1.2 Logstash

1.2.1 Logstash install

官網下載tar.gz版本的Logstash:https://www.elastic.co/cn/downloads/logstash,並上傳至/opt目錄。

tar xzvf logstash-5.6.3.tar.gz

cd logstash-5.6.3

bin/logstash -e 'input { stdin { } } output { stdout {} }'

在命令行下輸入hello world,將看到logstash的輸出內容:

 

1.2.2 logstash-input-jdbc

logstash-input-jdbc可以將數據庫中的數據導入進Elasticsearch。Logstash 5自帶了該插件。可以通過bin/logstash-pluginlist查看已安裝的插件。

       第一步,新建文件mysql.conf,放入Logstash根目錄:

input {

  stdin {

  }

  jdbc {

       jdbc_connection_string => "jdbc:mysql://10.8.9.85:3306/intelligence"

       jdbc_user => "root"

   jdbc_password => "yttest"

     jdbc_driver_library => "/opt/mysql-connector-java-5.1.6.jar"

     jdbc_driver_class => "com.mysql.jdbc.Driver"

     jdbc_paging_enabled => "true"

     jdbc_page_size => "50000"

     statement_filepath => "mysql.sql"

   schedule => "* * * * *"

   type => "jdbc"

  }

}

output {

  elasticsearch {

    hosts  => "localhost:9200"

    index => "demo"

    document_type => "news"

    document_id => "%{id}"

  }

  stdout {

    codec => json_lines

  }

}

第二步,新建文件mysql.sql,放入Logstash根目錄:

select * from inf_news

       第三步,啓動Logstash:

bin/logstash -f mysql.conf

       看到如下輸出,則啓動成功:

       查看Elasticsearch中的數據:

curl "http://localhost:9200/demo/news/_search"

       或者使用elasticsearch-head插件查看:

1.3 Kibana

1.3.1 Kibana install

官網下載tar.gz版本的Kibana:https://www.elastic.co/cn/downloads/kibana,並上傳至/opt目錄。

第一步,修改config/kibana.yml:

viconfig/kibana.yml

elasticsearch.url: "http://localhost:9200"

server.host: "0.0.0.0"

第二步,啓動kibana:

bin/kibana

       訪問http://localhost:5601

 

 

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章