Elasticsearch學習筆記

1、概述

一、什麼是搜索

  百度:咱們好比說想找尋任何的信息的時候,就會上百度去搜索一下,好比說找一部本身喜歡的電影,或者說找一本喜歡的書,或者找一條感興趣的新聞(提到搜索的第一印象)。百度 != 搜索
  1)互聯網的搜索:電商網站,招聘網站,新聞網站,各類app
  2)IT系統的搜索:OA軟件,辦公自動化軟件,會議管理,日程管理,項目管理。
  搜索,就是在任何場景下,找尋你想要的信息,這個時候,會輸入一段你要搜索的關鍵字,而後就指望找到這個關鍵字相關的有些信息html

二、用數據庫作搜索

  用數據庫來實現搜索,是不太靠譜的。一般來講,性能會不好的。前端

三、全文檢索和Lucene

  1)全文檢索,倒排索引
  全文檢索是指計算機索引程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先創建的索引進行查找,並將查找的結果反饋給用戶的檢索方式。這個過程相似於經過字典中的檢索字表查字的過程。全文搜索引擎數據庫中的數據。java

  • 倒排索引

傳統數據庫存儲:node

id 描述
1 優秀員工
2 銷售冠軍
3 優秀團隊領導
4 優秀項目

倒排索引處理步驟:mysql

一、切詞:
優秀員工 —— 優秀 員工
銷售冠軍 —— 銷售 冠軍
優秀團隊領導 —— 優秀 團隊 領導
優秀項目 —— 優秀 項目linux

二、創建倒排索引:
關鍵詞 idios

關鍵詞 id
優秀 1,3,4
員工 1
銷售 2
團隊 3
。。。 。。。

  2)lucene,就是一個jar包,裏面包含了封裝好的各類創建倒排索引,以及進行搜索的代碼,包括各類算法。咱們就用java開發的時候,引入lucene jar,而後基於lucene的api進行去進行開發就能夠了。git

四、什麼是Elasticsearch

  Elasticsearch,基於lucene,隱藏複雜性,提供簡單易用的restful api接口、java api接口(還有其餘語言的api接口)。
  關於elasticsearch的一個傳說,有一個程序員失業了,陪着本身老婆去英國倫敦學習廚師課程。程序員在失業期間想給老婆寫一個菜譜搜索引擎,以爲lucene實在太複雜了,就開發了一個封裝了lucene的開源項目,compass。後來程序員找到了工做,是作分佈式的高性能項目的,以爲compass不夠,就寫了elasticsearch,讓lucene變成分佈式的系統。
  Elasticsearch是一個實時分佈式搜索和分析引擎。它用於全文搜索、結構化搜索、分析。
  全文檢索:將非結構化數據中的一部分信息提取出來,從新組織,使其變得有必定結構,而後對此有必定結構的數據進行搜索,從而達到搜索相對較快的目的。
  結構化檢索:我想搜索商品分類爲日化用品的商品都有哪些,select * from products where category_id='日化用品'。
  數據分析:電商網站,最近7天牙膏這種商品銷量排名前10的商家有哪些;新聞網站,最近1個月訪問量排名前3的新聞版塊是哪些。程序員

五、Elasticsearch適用場景

  1)維基百科,相似百度百科,牙膏,牙膏的維基百科,全文檢索,高亮,搜索推薦。
  2)The Guardian(國外新聞網站),相似搜狐新聞,用戶行爲日誌(點擊,瀏覽,收藏,評論)+ 社交網絡數據(對某某新聞的相關見解),數據分析,給到每篇新聞文章的做者,讓他知道他的文章的公衆反饋(好,壞,熱門,垃圾,鄙視,崇拜)。
  3)Stack Overflow(國外的程序異常討論論壇),IT問題,程序的報錯,提交上去,有人會跟你討論和回答,全文檢索,搜索相關問題和答案,程序報錯了,就會將報錯信息粘貼到裏面去,搜索有沒有對應的答案。
  4)GitHub(開源代碼管理),搜索上千億行代碼。
  5)國內:站內搜索(電商,招聘,門戶,等等),IT系統搜索(OA,CRM,ERP,等等),數據分析(ES熱門的一個使用場景)。github

六、Elasticsearch特色

  1)能夠做爲一個大型分佈式集羣(數百臺服務器)技術,處理PB級數據,服務大公司;也能夠運行在單機上,服務小公司;樹莓派
  2)Elasticsearch不是什麼新技術,主要是將全文檢索、數據分析以及分佈式技術,合併在了一塊兒,才造成了獨一無二的ES;lucene(全文檢索),商用的數據分析軟件(也是有的),分佈式數據庫(mycat);
  3)對用戶而言,是開箱即用的,很是簡單,做爲中小型的應用,直接3分鐘部署一下ES,就能夠做爲生產環境的系統來使用了,數據量不大,操做不是太複雜;
  4)數據庫的功能面對不少領域是不夠用的(事務,還有各類聯機事務型的操做);特殊的功能,好比全文檢索,同義詞處理,相關度排名,複雜數據分析,海量數據的近實時處理;Elasticsearch做爲傳統數據庫的一個補充,提供了數據庫所不能提供的不少功能。

七、Elasticsearch核心概念

  • 近實時

  近實時,兩個意思,從寫入數據到數據能夠被搜索到有一個小延遲(大概1秒);基於es執行搜索和分析能夠達到秒級。

  • Cluster(集羣)

  集羣包含多個節點,每一個節點屬於哪一個集羣是經過一個配置(集羣名稱,默認是elasticsearch)來決定的,對於中小型應用來講,剛開始一個集羣就一個節點很正常。

  • Node(節點)

  集羣中的一個節點,節點也有一個名稱(默認是隨機分配的),節點名稱很重要(在執行運維管理操做的時候),默認節點會去加入一個名稱爲「elasticsearch」的集羣,若是直接啓動一堆節點,那麼它們會自動組成一個elasticsearch集羣,固然一個節點也能夠組成一個elasticsearch集羣。

  • Index(索引-數據庫)

  索引包含一堆有類似結構的文檔數據,好比能夠有一個客戶索引,商品分類索引,訂單索引,索引有一個名稱。一個index包含不少document,一個index就表明了一類相似的或者相同的document。好比說創建一個product index,商品索引,裏面可能就存放了全部的商品數據,全部的商品document。

  • Type(類型-表)

  每一個索引裏均可以有一個或多個type,type是index中的一個邏輯數據分類,一個type下的document,都有相同的field,好比博客系統,有一個索引,能夠定義用戶數據type,博客數據type,評論數據type。
  商品index,裏面存放了全部的商品數據,商品document
  可是商品分不少種類,每一個種類的document的field可能不太同樣,好比說電器商品,可能還包含一些諸如售後時間  範圍這樣的特殊field;生鮮商品,還包含一些諸如生鮮保質期之類的特殊field
  type,日化商品type,電器商品type,生鮮商品type
  日化商品type:product_id,product_name,product_desc,category_id,category_name
  電器商品type:product_id,product_name,product_desc,category_id,category_name,service_period
  生鮮商品type:product_id,product_name,product_desc,category_id,category_name,eat_period

  每個type裏面,都會包含一堆document

{
  "product_id": "1",
  "product_name": "長虹電視機",
  "product_desc": "4k高清",
  "category_id": "3",
  "category_name": "電器",
  "service_period": "1年"
}
{
  "product_id": "2",
  "product_name": "基圍蝦",
  "product_desc": "純自然,冰島產",
  "category_id": "4",
  "category_name": "生鮮",
  "eat_period": "7天"
}
  • Document(文檔-行)

  文檔是es中的最小數據單元,一個document能夠是一條客戶數據,一條商品分類數據,一條訂單數據,一般用JSON數據結構表示,每一個index下的type中,均可以去存儲多個document。

  • Field(字段-列)

  Field是Elasticsearch的最小單位。一個document裏面有多個field,每一個field就是一個數據字段。

product document
{
  "product_id": "1",
  "product_name": "高露潔牙膏",
  "product_desc": "高效美白",
  "category_id": "2",
  "category_name": "日化用品"
}
  • mapping(映射-約束)

  數據如何存放到索引對象上,須要有一個映射配置,包括:數據類型、是否存儲、是否分詞等。
  這樣就建立了一個名爲blog的Index。Type不用單首創建,在建立Mapping 時指定就能夠。Mapping用來定義Document中每一個字段的類型,即所使用的 analyzer、是否索引等屬性,很是關鍵等。建立Mapping 的代碼示例以下:

client.indices.putMapping({
    index : 'blog',
    type : 'article',
    body : {
        article: {
            properties: {
                id: {
                    type: 'string',
                    analyzer: 'ik',
                    store: 'yes',
                },
                title: {
                    type: 'string',
                    analyzer: 'ik',
                    store: 'no',
                },
                content: {
                    type: 'string',
                    analyzer: 'ik',
                    store: 'yes',
                }
            }
        }
    }
});
  • elasticsearch與數據庫的類比
關係型數據庫(好比Mysql) 非關係型數據庫(Elasticsearch)
數據庫Database 索引Index
表Table 類型Type
數據行Row 文檔Document
數據列Column 字段Field
約束 Schema 映射Mapping
  • ES存入數據和搜索數據機制

  1)索引對象(index):存儲數據的表結構 ,任何搜索數據,存放在索引對象上 。
  2)映射(mapping):數據如何存放到索引對象上,須要有一個映射配置, 包括:數據類型、是否存儲、是否分詞等。
  3)文檔(document):一條數據記錄,存在索引對象上 。
  4)文檔類型(type):一個索引對象,存放多種類型數據,數據用文檔類型進行標識。

二 快速入門

  單機版;head插件安裝;集羣搭建。

一、安裝包下載

二、安裝Elasticsearch(單節點Linux環境)

  • 1)解壓elasticsearch-5.6.1.tar.gz到/opt/module目錄下
[itstar@hadoop102 software]$ tar -zxvf elasticsearch-5.6.1.tar.gz -C /opt/module/
  • 2)在/opt/module/elasticsearch-5.6.1路徑下建立data和logs文件夾
[itstar@hadoop102 elasticsearch-5.6.1]$ mkdir data
[itstar@hadoop102 elasticsearch-5.6.1]$ mkdir logs
  • 3)修改配置文件/opt/module/elasticsearch-5.2.2/config/elasticsearch.yml
[itstar@hadoop102 config]$ pwd
/opt/module/elasticsearch-5.6.1/config
[itstar@hadoop102 config]$ vi elasticsearch.yml
# ---------------------------------- Cluster -------------------------------------
cluster.name: my-application
# ------------------------------------ Node --------------------------------------
node.name: node-102
# ----------------------------------- Paths ---------------------------------------
path.data: /opt/module/elasticsearch-5.6.1/data
path.logs: /opt/module/elasticsearch-5.6.1/logs
# ----------------------------------- Memory -----------------------------------
bootstrap.memory_lock: false
bootstrap.system_call_filter: false
# ---------------------------------- Network ------------------------------------
network.host: 192.168.1.102 
# --------------------------------- Discovery ------------------------------------
discovery.zen.ping.unicast.hosts: ["hadoop102"]

  (1)cluster.name
  若是要配置集羣須要兩個節點上的elasticsearch配置的cluster.name相同,都啓動能夠自動組成集羣,這裏若是不改cluster.name則默認是cluster.name=my-application,
  (2)nodename隨意取可是集羣內的各節點不能相同
  (3)修改後的每行前面不能有空格,修改後的「:」後面必須有一個空格

  (1)編輯limits.conf 添加相似以下內容

[itstar@hadoop102 elasticsearch-5.6.1]$ sudo vi /etc/security/limits.conf
添加以下內容:
* soft nofile 65536
* hard nofile 131072
* soft nproc 4096
* hard nproc 4096

  (2)進入limits.d目錄下修改配置文件。

[itstar@hadoop102 elasticsearch-5.6.1]$ sudo vi /etc/security/limits.d/90-nproc.conf
修改以下內容:
* soft nproc 1024
#修改成
* soft nproc 4096

  (3)修改配置sysctl.conf

[itstar@hadoop102 elasticsearch-5.6.1]$ sudo vi /etc/sysctl.conf 
添加下面配置:
vm.max_map_count=655360
並執行命令:
[itstar@hadoop102 elasticsearch-5.6.1]$ sudo sysctl -p
而後,從新啓動elasticsearch,便可啓動成功。
  • 5)啓動elasticsearch
[itstar@hadoop105 elasticsearch-5.6.1]$ bin/elasticsearch
  • 6)測試elasticsearch
[itstar@hadoop102 elasticsearch-5.6.1]$ curl http://hadoop102:9200
curl -XGET 'localhost:9200/_cat/health?v&pretty'

{
  "name" : "node-102",
  "cluster_name" : "my-application",
  "cluster_uuid" : "znZfW5tGQou9rKzb6pG6vA",
  "version" : {
    "number" : "5.6.1",
    "build_hash" : "667b497",
    "build_date" : "2017-09-14T19:22:05.189Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

  • 7)安裝elasticsearch-head.crx插件

  第一種安裝方法:
  (1)Google瀏覽器:打開瀏覽器,進入「更多工具」——>「擴展程序」,將插件拖入便可完成安裝
  (2)360瀏覽器:打開瀏覽器,雙擊elasticsearch-head.crx插件便可完成安裝
  (3)使用插件查看節點狀態

  第二種安裝方法:
  下載插件:https://github.com/mobz/elasticsearch-head
  nodejs官網下載安裝包:https://nodejs.org/dist/
  node-v6.9.2-linux-x64.tar.xz
  拷貝
  安裝nodejs:
  解壓
  配置環境變量:

export NODE_HOME=/usr/local/node-v6.9.2-linux-x64 export PATH=$PATH:$NODE_HOME/bin

  查看node和npm版本:

node -v
npm -v

  解壓head插件到/opt/module目錄下:

unzip elasticsearch-head-master.zip

  查看當前head插件目錄下有無node_modules/grunt目錄:
  沒有:執行命令建立:

npm install grunt --save --registry=https://registry.npm.taobao.org

  安裝head插件:

npm install -g cnpm --registry=https://registry.npm.taobao.org

  安裝grunt:

npm install -g grunt-cli --registry=https://registry.npm.taobao.org

  編輯Gruntfile.js

vim Gruntfile.js

  文件93行添加

hostname:'0.0.0.0'

  檢查head根目錄下是否存在base文件夾
  沒有:將 _site下的base文件夾及其內容複製到head根目錄下

mkdir base
cp base/* ../base/

  啓動grunt server:

grunt server -d

  若是提示grunt的模塊沒有安裝:

Local Npm module 「grunt-contrib-clean」 not found. Is it installed? 
Local Npm module 「grunt-contrib-concat」 not found. Is it installed? 
Local Npm module 「grunt-contrib-watch」 not found. Is it installed? 
Local Npm module 「grunt-contrib-connect」 not found. Is it installed? 
Local Npm module 「grunt-contrib-copy」 not found. Is it installed? 
Local Npm module 「grunt-contrib-jasmine」 not found. Is it installed?

  執行如下命令:

npm install grunt-contrib-clean -registry=https://registry.npm.taobao.org
npm install grunt-contrib-concat -registry=https://registry.npm.taobao.org
npm install grunt-contrib-watch -registry=https://registry.npm.taobao.org 
npm install grunt-contrib-connect -registry=https://registry.npm.taobao.org
npm install grunt-contrib-copy -registry=https://registry.npm.taobao.org 
npm install grunt-contrib-jasmine -registry=https://registry.npm.taobao.org

  最後一個模塊可能安裝不成功,可是不影響使用。
  瀏覽器訪問head插件:
  http://192.168.109.133:9100

  • 8)中止集羣
kill -9 進程號

三、安裝Elasticsearch(多節點集羣Linux環境)

  • 1)分發Elasticsearch安裝包至hadoop103和hadoop104
[itstar@hadoop102 module]$ xsync elasticsearch-5.6.1/
  • 2)修改hadoop102配置信息
[itstar@hadoop102 config]$ vi elasticsearch.yml

添加以下信息:

node.master: true
node.data: true
  • 3)修改hadoop103配置信息

  (1)修改Elasticsearch配置信息

[itstar@hadoop103 config]$ vi elasticsearch.yml
node.name: node-103
node.master: false
node.data: true
network.host: 192.168.1.103

  (2)修改Linux相關配置信息(同hadoop102)

  • 4)修改hadoop104配置信息

  (1)修改Elasticsearch配置信息

[itstar@hadoop104 config]$ vi elasticsearch.yml
node.name: node-104
node.master: false
node.data: true
network.host: 192.168.1.104

  (2)修改Linux相關配置信息(同hadoop102)

  • 5)分別啓動三臺節點的Elasticsearch

  • 6)使用插件查看集羣狀態

三 Java API操做

一、API基本操做

一、操做環境準備

  • 1)建立maven工程

  • 2)添加pom文件
<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.elasticsearch</groupId>
			<artifactId>elasticsearch</artifactId>
			<version>5.6.1</version>
		</dependency>

		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>transport</artifactId>
			<version>5.6.1</version>
		</dependency>

		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.9.0</version>
		</dependency>
	</dependencies>
  • 3)等待依賴的jar包下載完成

  當直接在ElasticSearch 創建文檔對象時,若是索引不存在的,默認會自動建立,映射採用默認方式

二、獲取Transport Client

  (1)ElasticSearch服務默認端口9300。
  (2)Web管理平臺端口9200。
  //org.elasticsearch.transport.client.PreBuiltTransportClient@4bff2185
  //org.elasticsearch.transport.client.PreBuiltTransportClient@6f099cef

private TransportClient client;

	@SuppressWarnings("unchecked")
	@Before
	public void getClient() throws Exception {

		// 1 設置鏈接的集羣名稱
		Settings settings = Settings.builder().put("cluster.name", "my-application").build();

		// 2 鏈接集羣
		client = new PreBuiltTransportClient(settings);
		client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("hadoop102"), 9300));

		// 3 打印集羣名稱
		System.out.println(client.toString());
	}

  (3)顯示log4j2報錯,在resource目錄下建立一個文件命名爲log4j2.xml並添加以下內容

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

三、建立索引

  • 1)源代碼
@Test
	public void createIndex_blog(){
		// 1 建立索引
		client.admin().indices().prepareCreate("blog2").get();
		
		// 2 關閉鏈接
		client.close();
	}
  • 2)查看結果
{"blog2":{"aliases":{},"mappings":{},"settings":{"index":{"creation_date":"1507466730030","number_of_shards":"5","number_of_replicas":"1","uuid":"lec0xYiBSmStspGVa6c80Q","version":{"created":"5060299"},"provided_name":"blog2"}}}}

四、刪除索引

  • 1)源代碼
@Test
	public void deleteIndex(){
		// 1 刪除索引
		client.admin().indices().prepareDelete("blog2").get();
		
		// 2 關閉鏈接
		client.close();
	}
  • 2)查看結果
瀏覽器查看http://hadoop102:9200/blog2
沒有blog2索引了。
{"error":{"root_cause":[{"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"blog2","index_uuid":"_na_","index":"blog2"}],"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"blog2","index_uuid":"_na_","index":"blog2"},"status":404}

五、新建文檔(源數據json串)

  當直接在ElasticSearch創建文檔對象時,若是索引不存在的,默認會自動建立,映射採用默認方式。

  • 1)源代碼
@Test
	public void createIndexByJson() throws UnknownHostException {

		// 1 文檔數據準備
		String json = "{" + "\"id\":\"1\"," + "\"title\":\"基於Lucene的搜索服務器\","
				+ "\"content\":\"它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口\"" + "}";

		// 2 建立文檔
		IndexResponse indexResponse = client.prepareIndex("blog", "article", "1").setSource(json).execute().actionGet();

		// 3 打印返回的結果
		System.out.println("index:" + indexResponse.getIndex());
		System.out.println("type:" + indexResponse.getType());
		System.out.println("id:" + indexResponse.getId());
		System.out.println("version:" + indexResponse.getVersion());
		System.out.println("result:" + indexResponse.getResult());

		// 4 關閉鏈接
		client.close();
	}
  • 2)結果查看

六、新建文檔(源數據map方式添加json)

  • 1)源代碼
@Test
	public void createIndexByMap() {

		// 1 文檔數據準備
		Map<String, Object> json = new HashMap<String, Object>();
		json.put("id", "2");
		json.put("title", "基於Lucene的搜索服務器");
		json.put("content", "它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口");

		// 2 建立文檔
		IndexResponse indexResponse = client.prepareIndex("blog", "article", "2").setSource(json).execute().actionGet();

		// 3 打印返回的結果
		System.out.println("index:" + indexResponse.getIndex());
		System.out.println("type:" + indexResponse.getType());
		System.out.println("id:" + indexResponse.getId());
		System.out.println("version:" + indexResponse.getVersion());
		System.out.println("result:" + indexResponse.getResult());

		// 4 關閉鏈接
		client.close();
	}
  • 2)結果查看

七、新建文檔(源數據es構建器添加json)

  • 1)源代碼
@Test
	public void createIndex() throws Exception {

		// 1 經過es自帶的幫助類,構建json數據
		XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("id", 3).field("title", "基於Lucene的搜索服務器").field("content", "它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。")
				.endObject();

		// 2 建立文檔
		IndexResponse indexResponse = client.prepareIndex("blog", "article", "3").setSource(builder).get();

		// 3 打印返回的結果
		System.out.println("index:" + indexResponse.getIndex());
		System.out.println("type:" + indexResponse.getType());
		System.out.println("id:" + indexResponse.getId());
		System.out.println("version:" + indexResponse.getVersion());
		System.out.println("result:" + indexResponse.getResult());

		// 4 關閉鏈接
		client.close();
	}
  • 2)結果查看

八、搜索文檔數據(單個索引)

  • 1)源代碼
@Test
	public void getData() throws Exception {
		
		// 1 查詢文檔
		GetResponse response = client.prepareGet("blog", "article", "1").get();
		
		// 2 打印搜索的結果
		System.out.println(response.getSourceAsString());
		
		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

九、搜索文檔數據(多個索引)

  • 1)源代碼
@Test
	public void getMultiData() {
		
		// 1 查詢多個文檔
		MultiGetResponse response = client.prepareMultiGet().add("blog", "article", "1").add("blog", "article", "2", "3").add("blog", "article", "2").get();
		
		// 2 遍歷返回的結果
		for(MultiGetItemResponse itemResponse:response){
			GetResponse getResponse = itemResponse.getResponse();
			
			// 若是獲取到查詢結果
			if (getResponse.isExists()) {
				String sourceAsString = getResponse.getSourceAsString();
				System.out.println(sourceAsString);
			}
		}
		
		// 3 關閉資源
		client.close();
	}
  • 2)結果查看
{"id":"1","title":"基於Lucene的搜索服務器","content":"它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口"}
{"content":"它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口","id":"2","title":"基於Lucene的搜索服務器"}
{"id":3,"titile":"ElasticSearch是一個基於Lucene的搜索服務器","content":"它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。"}
{"content":"它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口","id":"2","title":"基於Lucene的搜索服務器"}

十、更新文檔數據(update)

  • 1)源代碼
@Test
	public void updateData() throws Throwable {

		// 1 建立更新數據的請求對象
		UpdateRequest updateRequest = new UpdateRequest();
		updateRequest.index("blog");
		updateRequest.type("article");
		updateRequest.id("3");

		updateRequest.doc(XContentFactory.jsonBuilder().startObject()
				// 對沒有的字段添加, 對已有的字段替換
				.field("title", "基於Lucene的搜索服務器")
				.field("content","它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。大數據前景無限")
				.field("createDate", "2017-8-22").endObject());

		// 2 獲取更新後的值
		UpdateResponse indexResponse = client.update(updateRequest).get();
		
		// 3 打印返回的結果
		System.out.println("index:" + indexResponse.getIndex());
		System.out.println("type:" + indexResponse.getType());
		System.out.println("id:" + indexResponse.getId());
		System.out.println("version:" + indexResponse.getVersion());
		System.out.println("create:" + indexResponse.getResult());

		// 4 關閉鏈接
		client.close();
	}
  • 2)結果查看

十一、更新文檔數據(upsert)

  設置查詢條件, 查找不到則添加IndexRequest內容,查找到則按照UpdateRequest更新。

@Test
	public void testUpsert() throws Exception {

		// 設置查詢條件, 查找不到則添加
		IndexRequest indexRequest = new IndexRequest("blog", "article", "5")
				.source(XContentFactory.jsonBuilder().startObject().field("title", "搜索服務器").field("content","它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並做爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,可以達到實時搜索,穩定,可靠,快速,安裝使用方便。").endObject());
		
		// 設置更新, 查找到更新下面的設置
		UpdateRequest upsert = new UpdateRequest("blog", "article", "5")
				.doc(XContentFactory.jsonBuilder().startObject().field("user", "李四").endObject()).upsert(indexRequest);

		client.update(upsert).get();
		client.close();
	}

  第一次執行
  hadoop102:9200/blog/article/5

  第二次執行
  hadoop102:9200/blog/article/5

十二、刪除文檔數據(prepareDelete)

  • 1)源代碼
@Test
	public void deleteData() {
		
		// 1 刪除文檔數據
		DeleteResponse indexResponse = client.prepareDelete("blog", "article", "5").get();

		// 2 打印返回的結果
		System.out.println("index:" + indexResponse.getIndex());
		System.out.println("type:" + indexResponse.getType());
		System.out.println("id:" + indexResponse.getId());
		System.out.println("version:" + indexResponse.getVersion());
		System.out.println("found:" + indexResponse.getResult());

		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

2 條件查詢QueryBuilder

二、條件查詢QueryBuilder

一、查詢全部(matchAllQuery)

  • 1)源代碼
@Test
	public void matchAllQuery() {
		
		// 1 執行查詢
		SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
				.setQuery(QueryBuilders.matchAllQuery()).get();

		// 2 打印查詢結果
		SearchHits hits = searchResponse.getHits(); // 獲取命中次數,查詢結果有多少對象
		System.out.println("查詢結果有:" + hits.getTotalHits() + "條");

		for (SearchHit hit : hits) {
           System.out.println(hit.getSourceAsString());//打印出每條結果
        }

		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

二、對全部字段分詞查詢(queryStringQuery)

  • 1)源代碼
@Test
	public void query() {
		// 1 條件查詢
		SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
				.setQuery(QueryBuilders.queryStringQuery("全文")).get();

		// 2 打印查詢結果
		SearchHits hits = searchResponse.getHits(); // 獲取命中次數,查詢結果有多少對象
		System.out.println("查詢結果有:" + hits.getTotalHits() + "條");
		
		for (SearchHit hit : hits) {
           System.out.println(hit.getSourceAsString());//打印出每條結果
        }
		
		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

3 通配符查詢(wildcardQuery)

  * :表示多個字符(0個或多個字符)
  ?:表示單個字符
  1)源代碼

@Test
	public void wildcardQuery() {

		// 1 通配符查詢
		SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
				.setQuery(QueryBuilders.wildcardQuery("content", "*全*")).get();

		// 2 打印查詢結果
		SearchHits hits = searchResponse.getHits(); // 獲取命中次數,查詢結果有多少對象
		System.out.println("查詢結果有:" + hits.getTotalHits() + "條");

		for (SearchHit hit : hits) {
           System.out.println(hit.getSourceAsString());//打印出每條結果
        }

		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

四、詞條查詢(TermQuery)

  • 1)源代碼
@Test
	public void termQuery() {
		
		// 1 第一field查詢
		SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
				.setQuery(QueryBuilders.termQuery("content", "全文")).get();
		
		// 2 打印查詢結果
		SearchHits hits = searchResponse.getHits(); // 獲取命中次數,查詢結果有多少對象
		System.out.println("查詢結果有:" + hits.getTotalHits() + "條");

		for (SearchHit hit : hits) {
           System.out.println(hit.getSourceAsString());//打印出每條結果
        }

		// 3 關閉鏈接
		client.close();
	}
  • 2)結果查看

五、模糊查詢(fuzzy)

@Test
	public void fuzzy() {
		
		// 1 模糊查詢
		SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
				.setQuery(QueryBuilders.fuzzyQuery("title", "lucene")).get();
		
		// 2 打印查詢結果
		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()); // 獲取字符串格式打印
		}

		// 3 關閉鏈接
		client.close();
	}

三、映射相關操做

  • 1)源代碼
@Test
	public void createMapping() throws Exception {
		
		// 1設置mapping
		XContentBuilder builder = XContentFactory.jsonBuilder()
				.startObject()
					.startObject("article")
						.startObject("properties")
							.startObject("id1")
								.field("type", "string")
								.field("store", "yes")
							.endObject()
							.startObject("title2")
								.field("type", "string")
								.field("store", "no")
							.endObject()
							.startObject("content")
								.field("type", "string")
								.field("store", "yes")
							.endObject()
						.endObject()
					.endObject()
				.endObject();

		// 2 添加mapping
		PutMappingRequest mapping = Requests.putMappingRequest("blog4").type("article").source(builder);
		
		client.admin().indices().putMapping(mapping).get();
		
		// 3 關閉資源
		client.close();
	}
  • 2)查看結果

4、IK分詞器

  針對詞條查詢(TermQuery),查看默認中文分詞器的效果:

[itstar@hadoop105 elasticsearch]$  curl -XGET 'http://hadoop105:9200/_analyze?pretty&analyzer=standard' -d '中華人民共和國'
{
  "tokens" : [
    {
      "token" : "中",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "華",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "人",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "民",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "共",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "和",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "國",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 6
    }
  ]
}

一、IK分詞器的安裝

1 前期準備工做

  • 1)CentOS聯網

  配置CentOS能鏈接外網。Linux虛擬機ping www.baidu.com 是暢通的

  • 2)jar包準備

  (1)elasticsearch-analysis-ik-master.zip
  (下載地址:https://github.com/medcl/elasticsearch-analysis-ik)
  (2)apache-maven-3.0.5-bin.tar.gz

二、jar包安裝

1)Maven解壓、配置  MAVEN_HOME和PATH。

[itstar@hadoop102 software]# tar -zxvf apache-maven-3.0.5-bin.tar.gz -C /opt/module/
[itstar@hadoop102 apache-maven-3.0.5]# sudo vi /etc/profile

#MAVEN_HOME
export MAVEN_HOME=/opt/module/apache-maven-3.0.5
export PATH=$PATH:$MAVEN_HOME/bin

[itstar@hadoop101 software]#source /etc/profile
驗證命令:mvn -version
  • 2)Ik分詞器解壓、打包與配置
//ik分詞器解壓
[itstar@hadoop102 software]$ unzip elasticsearch-analysis-ik-master.zip -d ./

//進入ik分詞器所在目錄
[itstar@hadoop102 software]$ cd elasticsearch-analysis-ik-master

//使用maven進行打包
[itstar@hadoop102 elasticsearch-analysis-ik-master]$ mvn package -Pdist,native -DskipTests -Dtar

//打包完成以後,會出現 target/releases/elasticsearch-analysis-ik-{version}.zip
[itstar@hadoop102 releases]$ pwd 	/opt/software/elasticsearch-analysis-ik-master/target/releases

//對zip文件進行解壓,並將解壓完成以後的文件拷貝到es所在目錄下的/plugins/
[itstar@hadoop102 releases]$ unzip elasticsearch-analysis-ik-6.0.0.zip
[itstar@hadoop102 releases]$ cp -r elasticsearch /opt/module/elasticsearch-5.6.1/plugins/

//須要修改plugin-descriptor.properties文件,將其中的es版本號改成你所使用的版本號,即完成ik分詞器的安裝
[itstar@hadoop102 elasticsearch]$ vi plugin-descriptor.properties

//71行
elasticsearch.version=6.0.0
//修改成
elasticsearch.version=5.6.1

  注意:需選擇與es相同版本的ik分詞器。
  安裝方法(2種):

  1.

./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.1.1/elasticsearch-analysis-ik-6.1.1.zip

  2.

cp elasticsearch-analysis-ik-6.1.1.zip ./elasticsearch-6.1.1/plugins/
unzip elasticsearch-analysis-ik-6.1.1.zip -d ik-analyzer

三、

elasticsearch-plugin install -f file:///usr/local/elasticsearch-analysis-ik-6.1.1.zip

二、IK分詞器的使用

一、命令行查看結果

  • ik_smart模式
[itstar@hadoop102 elasticsearch]$ curl -XGET 'http://hadoop104:9200/_analyze?pretty&analyzer=ik_smart' -d '中華人民共和國'

curl -H "Content-Type:application/json" -XGET 'http://192.168.109.133:9200/_analyze?pretty' -d '{"analyzer":"ik_smart","text":"中華人民共和國"}'

{
  "tokens" : [
    {
      "token" : "中華人民共和國",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 0
    }
  ]
}
  • ik_max_word模式
[itstar@hadoop102 elasticsearch]$ curl -XGET 'http://hadoop104:9200/_analyze?pretty&analyzer=ik_max_word' -d '中華人民共和國'

curl -H "Content-Type:application/json" -XGET 'http://192.168.109.133:9200/_analyze?pretty' -d '{"analyzer":"ik_max_word","text":"中華人民共和國"}'

{
  "tokens" : [
    {
      "token" : "中華人民共和國",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "中華人民",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "中華",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "華人",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "人民共和國",
      "start_offset" : 2,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "人民",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "共和國",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "共和",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 7
    },
    {
      "token" : "國",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "CN_CHAR",
      "position" : 8
    }
  ]
}

2 JavaAPI操做

  • 1)建立索引
//建立索引(數據庫)
    @Test
    public void createIndex() {
        //建立索引
        client.admin().indices().prepareCreate("blog4").get();
        //關閉資源
        client.close();
    }
  • 2)建立mapping
//建立使用ik分詞器的mapping
    @Test
    public void createMapping() throws Exception {

        // 1設置mapping
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                    .startObject("article")
                        .startObject("properties")
                        .startObject("id1")
                            .field("type", "string")
                            .field("store", "yes")
                            .field("analyzer","ik_smart")
                        .endObject()
                        .startObject("title2")
                            .field("type", "string")
                            .field("store", "no")
                            .field("analyzer","ik_smart")
                        .endObject()
                        .startObject("content")
                            .field("type", "string")
                            .field("store", "yes")
                            .field("analyzer","ik_smart")
                        .endObject()
                        .endObject()
                    .endObject()
                .endObject();

        // 2 添加mapping
        PutMappingRequest mapping = Requests.putMappingRequest("blog4").type("article").source(builder);
        client.admin().indices().putMapping(mapping).get();

        // 3 關閉資源
        client.close();
    }
  • 3)插入數據
//建立文檔,以map形式
    @Test
    public void createDocumentByMap() {

        HashMap<String, String> map = new HashMap<>();
        map.put("id1", "2");
        map.put("title2", "Lucene");
        map.put("content", "它提供了一個分佈式的web接口");

        IndexResponse response = client.prepareIndex("blog4", "article", "3").setSource(map).execute().actionGet();

        //打印返回的結果
        System.out.println("結果:" + response.getResult());
        System.out.println("id:" + response.getId());
        System.out.println("index:" + response.getIndex());
        System.out.println("type:" + response.getType());
        System.out.println("版本:" + response.getVersion());

        //關閉資源
        client.close();
    }
  • 4)詞條查詢
//詞條查詢
    @Test
    public void queryTerm() {

        SearchResponse response = client.prepareSearch("blog4").setTypes("article").setQuery(QueryBuilders.termQuery("content","提供")).get();

        //獲取查詢命中結果
        SearchHits hits = response.getHits();

        System.out.println("結果條數:" + hits.getTotalHits());

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
  • 5)結果查看

  Store 的解釋:
  使用 elasticsearch 時碰上了很迷惑的地方,我看官方文檔說 store 默認是 no ,我想固然的理解爲也就是說這個 field 是不會 store 的,可是查詢的時候也能查詢出來,通過查找資料瞭解到原來 store 的意思是,是否在 _source 以外在獨立存儲一份,這裏要說一下 _source 這是源文檔,當你索引數據的時候, elasticsearch 會保存一份源文檔到 _source ,若是文檔的某一字段設置了 store 爲 yes (默認爲 no),這時候會在 _source 存儲以外再爲這個字段獨立進行存儲,這麼作的目的主要是針對內容比較多的字段,放到 _source 返回的話,由於_source 是把全部字段保存爲一份文檔,命中後讀取只須要一次 IO,包含內容特別多的字段會很佔帶寬影響性能,一般咱們也不須要完整的內容返回(可能只關心摘要),這時候就不必放到 _source 裏一塊兒返回了(固然也能夠在查詢時指定返回字段)。

5、Logstash

5.1 Logstash簡介

  Logstash is a tool for managing events and logs. You can use it to collect logs, parse them, and store them for later use (like, for searching).

  logstash是一個數據分析軟件,主要目的是分析log日誌。整一套軟件能夠看成一個MVC模型,logstash是controller層,Elasticsearch是一個model層,kibana是view層。

  首先將數據傳給logstash,它將數據進行過濾和格式化(轉成JSON格式),而後傳給Elasticsearch進行存儲、建搜索的索引,kibana提供前端的頁面再進行搜索和圖表可視化,它是調用Elasticsearch的接口返回的數據進行可視化。logstash和Elasticsearch是用Java寫的,kibana使用node.js框架。

  這個軟件官網有很詳細的使用說明,https://www.elastic.co/,除了docs以外,還有視頻教程。這篇博客集合了docs和視頻裏面一些比較重要的設置和使用。

二、Logstash 安裝

  直接下載官方發佈的二進制包的,能夠訪問 https://www.elastic.co/downloads/logstash 頁面找對應操做系統和版本,點擊下載便可。

  在終端中,像下面這樣運行命令來啓動 Logstash 進程:

# bin/logstash -e 'input{stdin{}}output{stdout{codec=>rubydebug}}'

  注意:若是出現以下報錯,請調高虛擬機內存容量。

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c5330000, 986513408, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 986513408 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /usr/local/logstash-6.6.2/confs_test/hs_err_pid3910.log

  而後你會發現終端在等待你的輸入。沒問題,敲入 Hello World,回車,

{
      "@version" => "1",
          "host" => "***",
       "message" => "hello world",
    "@timestamp" => 2019-03-18T02:51:18.578Z
}

  每位系統管理員都確定寫過不少相似這樣的命令:

cat randdata | awk '{print $2}' | sort | uniq -c | tee sortdata。

  Logstash 就像管道符同樣!
  你輸入(就像命令行的 cat )數據,而後處理過濾(就像 awk 或者 uniq 之類)數據,最後輸出(就像 tee )到其餘地方。

三、Logstash 配置

1 input配置

讀取文件(File)

input {
    file {
        path => ["/var/log/*.log", "/var/log/message"]
        type => "system"
        start_position => "beginning"
}

}
output{stdout{codec=>rubydebug}}

  有一些比較有用的配置項,能夠用來指定 FileWatch 庫的行爲:

  discover_interval
  logstash 每隔多久去檢查一次被監聽的 path 下是否有新文件。默認值是 15 秒。

  exclude
  不想被監聽的文件能夠排除出去,這裏跟 path 同樣支持 glob 展開。

  close_older
  一個已經監聽中的文件,若是超過這個值的時間內沒有更新內容,就關閉監聽它的文件句柄。默認是 3600 秒,即一小時。

  ignore_older
  在每次檢查文件列表的時候,若是一個文件的最後修改時間超過這個值,就忽略這個文件。默認是 86400 秒,即一天。

  sincedb_path
  若是你不想用默認的 $HOME/.sincedb(Windows 平臺上在 C:\Windows\System32\config\systemprofile.sincedb),能夠經過這個配置定義 sincedb 文件到其餘位置。

  sincedb_write_interval
  logstash 每隔多久寫一次 sincedb 文件,默認是 15 秒。

  stat_interval
  logstash 每隔多久檢查一次被監聽文件狀態(是否有更新),默認是 1 秒。

  start_position
  logstash 從什麼位置開始讀取文件數據,默認是結束位置,也就是說 logstash 進程會以相似 tail -F 的形式運行。若是你是要導入原有數據,把這個設定改爲 "beginning",logstash 進程就從頭開始讀取,相似 less +F 的形式運行。

  啓動命令:../bin/logstash -f ./input_file.conf
  測試命令:echo 'hehe' >> test.log echo 'hehe2' >> message

標準輸入(Stdin)

  咱們已經見過好幾個示例使用 stdin 了。這也應該是 logstash 裏最簡單和基礎的插件了。

input {
    stdin {
        add_field => {"key" => "value"}
        codec => "plain"
        tags => ["add"]
        type => "std"
    }
}
output{stdout{codec=>rubydebug}}

  用上面的新 stdin 設置從新運行一次最開始的 hello world 示例。我建議你們把整段配置都寫入一個文本文件,而後運行命令:../bin/logstash -f ./input_stdin.conf。輸入 "hello world" 並回車後,你會在終端看到以下輸出:

{
       "message" => "hello world",
      "@version" => "1",
    "@timestamp" => "2014-08-08T06:48:47.789Z",
          "type" => "std",
          "tags" => [
        [0] "add"
    ],
           "key" => "value",
          "host" => "raochenlindeMacBook-Air.local"
}

  解釋
  type 和 tags 是 logstash 事件中兩個特殊的字段。一般來講咱們會在輸入區段中經過 type 來標記事件類型。而 tags 則是在數據處理過程當中,由具體的插件來添加或者刪除的。

  最多見的用法是像下面這樣:

input {
    stdin {
        type => "web"
    }
}
filter {
    if [type] == "web" {
        grok {
            match => ["message", %{COMBINEDAPACHELOG}]
        }
    }
}
output {
    if "_grokparsefailure" in [tags] {
        nagios_nsca {
            nagios_status => "1"
        }
    } else {
        elasticsearch {
        }
    }
}

二、codec配置

  Codec 是 logstash 從 1.3.0 版開始新引入的概念(Codec 來自 Coder/decoder 兩個單詞的首字母縮寫)。

  在此以前,logstash 只支持純文本形式輸入,而後以過濾器處理它。但如今,咱們能夠在輸入期處理不一樣類型的數據,這全是由於有了 codec 設置。

  因此,這裏須要糾正以前的一個概念。Logstash 不僅是一個input | filter | output 的數據流,而是一個 input | decode | filter | encode | output 的數據流!codec 就是用來 decode、encode 事件的。

  codec 的引入,使得 logstash 能夠更好更方便的與其餘有自定義數據格式的運維產品共存,好比 graphite、fluent、netflow、collectd,以及使用 msgpack、json、edn 等通用數據格式的其餘產品等。

  事實上,咱們在第一個 "hello world" 用例中就已經用過 codec 了 —— rubydebug 就是一種 codec!雖然它通常只會用在 stdout 插件中,做爲配置測試或者調試的工具。

  採用 JSON 編碼
  在早期的版本中,有一種下降 logstash 過濾器的 CPU 負載消耗的作法盛行於社區(在當時的 cookbook 上有專門的一節介紹):直接輸入預約義好的 JSON 數據,這樣就能夠省略掉 filter/grok 配置!

  這個建議依然有效,不過在當前版本中須要稍微作一點配置變更 —— 由於如今有專門的 codec 設置。

  配置示例

input {
    stdin {
        add_field => {"key" => "value"}
        codec => "json"
        type => "std"
    }
}
output{stdout{codec=>rubydebug}}

輸入:
{"simCar":18074045598,"validityPeriod":"1996-12-06","unitPrice":9,"quantity":19,"amount":35,"imei":887540376467915,"user":"test"}

  運行結果:

{
              "imei" => 887540376467915,
         "unitPrice" => 9,
              "user" => "test",
        "@timestamp" => 2019-03-19T05:01:53.451Z,
            "simCar" => 18074045598,
              "host" => "zzc-203",
            "amount" => 35,
          "@version" => "1",
               "key" => "value",
              "type" => "std",
    "validityPeriod" => "1996-12-06",
          "quantity" => 19
}

三、filter配置

  • Grok插件

  logstash擁有豐富的filter插件,它們擴展了進入過濾器的原始數據,進行復雜的邏輯處理,甚至能夠無中生有的添加新的 logstash 事件到後續的流程中去!Grok 是 Logstash 最重要的插件之一。也是迄今爲止使蹩腳的、無結構的日誌結構化和可查詢的最好方式。Grok在解析 syslog logs、apache and other webserver logs、mysql logs等任意格式的文件上表現完美。

  這個工具很是適用於系統日誌,Apache和其餘網絡服務器日誌,MySQL日誌等。

配置:
input {
    stdin {
        type => "std"
    }
}
filter {
  grok {
    match=>{"message"=> "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
  }
}
output{stdout{codec=>rubydebug}}

輸入:55.3.244.1 GET /index.html 15824 0.043
輸出:
{
      "@version" => "1",
          "host" => "zzc-203",
       "request" => "/index.html",
         "bytes" => "15824",
      "duration" => "0.043",
        "method" => "GET",
    "@timestamp" => 2019-03-19T05:09:55.777Z,
       "message" => "55.3.244.1 GET /index.html 15824 0.043",
          "type" => "std",
        "client" => "55.3.244.1"
}

grok模式的語法以下:

  %{SYNTAX:SEMANTIC}

  SYNTAX:表明匹配值的類型,例如3.44能夠用NUMBER類型所匹配,127.0.0.1可使用IP類型匹配。
  SEMANTIC:表明存儲該值的一個變量名稱,例如 3.44 多是一個事件的持續時間,127.0.0.1多是請求的client地址。因此這兩個值能夠用 %{NUMBER:duration} %{IP:client} 來匹配。

  你也能夠選擇將數據類型轉換添加到Grok模式。默認狀況下,全部語義都保存爲字符串。若是您但願轉換語義的數據類型,例如將字符串更改成整數,則將其後綴爲目標數據類型。例如%{NUMBER:num:int}將num語義從一個字符串轉換爲一個整數。目前惟一支持的轉換是int和float。

  Logstash附帶約120個模式。你能夠在這裏找到它們https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns

  自定義類型

  更多時候logstash grok沒辦法提供你所須要的匹配類型,這個時候咱們可使用自定義。

  建立自定義 patterns 文件。
  ①建立一個名爲patterns其中建立一個文件postfix (文件名可有可無,隨便起),在該文件中,將須要的模式寫爲模式名稱,空格,而後是該模式的正則表達式。例如:

  POSTFIX_QUEUEID [0-9A-F]{10,11}

  ②而後使用這個插件中的patterns_dir設置告訴logstash目錄是你的自定義模式。

配置:
input {
    stdin {
        type => "std"
    }
}
filter {
  grok {
    patterns_dir => ["./patterns"]
    match => { "message" => "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{GREEDYDATA:syslog_message}" }
  }
}
output{stdout{codec=>rubydebug}}

輸入:
Jan  1 06:25:43 mailserver14 postfix/cleanup[21403]: BEF25A72965: message-id=<20130101142543.5828399CCAF@mailserver1

輸出:
{
          "queue_id" => "BEF25A72965",
           "message" => "Jan  1 06:25:43 mailserver14 postfix/cleanup[21403]: BEF25A72965: message-id=<20130101142543.5828399CCAF@mailserver1",
               "pid" => "21403",
           "program" => "postfix/cleanup",
          "@version" => "1",
              "type" => "std",
         "logsource" => "mailserver14",
              "host" => "zzc-203",
         "timestamp" => "Jan  1 06:25:43",
    "syslog_message" => "message-id=<20130101142543.5828399CCAF@mailserver1",
        "@timestamp" => 2019-03-19T05:31:37.405Z
}

GeoIP 地址查詢歸類

  GeoIP 是最多見的免費 IP 地址歸類查詢庫,同時也有收費版能夠採購。GeoIP 庫能夠根據 IP 地址提供對應的地域信息,包括國別,省市,經緯度等,對於可視化地圖和區域統計很是有用。

配置:
input {
    stdin {
        type => "std"
    }
}
filter {
    geoip {
        source => "message"
    }
}
output{stdout{codec=>rubydebug}}

輸入:183.60.92.253
輸出:
{
          "type" => "std",
      "@version" => "1",
    "@timestamp" => 2019-03-19T05:39:26.714Z,
          "host" => "zzc-203",
       "message" => "183.60.92.253",
         "geoip" => {
         "country_code3" => "CN",
              "latitude" => 23.1167,
           "region_code" => "44",
           "region_name" => "Guangdong",
              "location" => {
            "lon" => 113.25,
            "lat" => 23.1167
        },
             "city_name" => "Guangzhou",
          "country_name" => "China",
        "continent_code" => "AS",
         "country_code2" => "CN",
              "timezone" => "Asia/Shanghai",
                    "ip" => "183.60.92.253",
             "longitude" => 113.25
    }
}

四、output配置

標準輸出(Stdout)

保存成文件(File)

  經過日誌收集系統將分散在數百臺服務器上的數據集中存儲在某中心服務器上,這是運維最原始的需求。Logstash 固然也能作到這點。

  和 LogStash::Inputs::File 不一樣, LogStash::Outputs::File 裏可使用 sprintf format 格式來自動定義輸出到帶日期命名的路徑。

配置:
input {
    stdin {
        type => "std"
    }
}
output {
    file {
        path => "../data_test/%{+yyyy}/%{+MM}/%{+dd}/%{host}.log"
        codec => line { format => "custom format: %{message}"}
    }
}

  啓動後輸入,可看到文件

  服務器間傳輸文件(File)

//配置:
//接收日誌服務器配置:
input {
  tcp {
	mode => "server"
	port => 9600
	ssl_enable => false
  }
}
filter {
    json {
        source => "message"
    }
}
output {
    file {
        path => "/home/hduser/app/logstash-6.6.2/data_test/%{+YYYY-MM-dd}/%{servip}-%{filename}"
        codec => line { format => "%{message}"}
    }
}

//發送日誌服務器配置:
input{
    file {
        path => ["/home/hduser/app/logstash-6.6.2/data_test/send.log"]
        type => "ecolog"
        start_position => "beginning"
    }
}
filter {
    if [type] =~ /^ecolog/ {
        ruby {
            code => "file_name = event.get('path').split('/')[-1]
					 event.set('file_name',file_name)
					 event.set('servip','接收方ip')"
        }
        mutate {
            rename => {"file_name" => "filename"}
        }
    }
}
output {
	tcp {
        host  => "接收方ip"
        port  => 9600
        codec => json_lines
    }
}

  從發送方發送message,接收方能夠看到寫出文件。

寫入到ES

//配置:
input {
    stdin {
        type => "log2es"
    }
}
output {
    elasticsearch {
        hosts => ["192.168.109.133:9200"]
        index => "logstash-%{type}-%{+YYYY.MM.dd}"
        document_type => "%{type}"
        sniffing => true
        template_overwrite => true
    }
}

//在head插件中能夠看到數據。
//sniffing : 尋找其餘es節點

//實戰舉例:將錯誤日誌寫入es。
//配置:
input {
    file {
        path => ["/usr/local/logstash-6.6.2/data_test/run_error.log"]
        type => "error"
        start_position => "beginning"
}

}
output {
    elasticsearch {
        hosts => ["192.168.109.133:9200"]
        index => "logstash-%{type}-%{+YYYY.MM.dd}"
        document_type => "%{type}"
        sniffing => true
        template_overwrite => true
    }
}

  問題:一個錯誤被分紅了多個document。如何解決?

6、Kibana

  Kibana是一個開源的分析和可視化平臺,設計用於和Elasticsearch一塊兒工做。
  你用Kibana來搜索,查看,並和存儲在Elasticsearch索引中的數據進行交互。
  你能夠輕鬆地執行高級數據分析,而且以各類圖標、表格和地圖的形式可視化數據。
  Kibana使得理解大量數據變得很容易。它簡單的、基於瀏覽器的界面使你可以快速建立和共享動態儀表板,實時顯示Elasticsearch查詢的變化。

安裝步驟:

解壓:tar -zxvf kibana-6.6.2-linux-x86_64.tar.gz
修改 kibana.yml 配置文件:
server.port: 5601
server.host: "192.168.109.134"   ----------部署kinana服務器的ip
elasticsearch.hosts: ["http://192.168.109.133:9200"]
kibana.index: ".kibana"

啓動kibana,報錯:
[error][status][plugin:remote_clusters@6.6.2] Status changed from red to red - X-Pack plugin is not installed on the [data] Elasticsearch cluster.

解決,卸載x-pack插件。
elasticsearch-plugin remove x-pack
kibana-plugin remove x-pack

安裝好後啓動便可。頁面操做。
相關文章
相關標籤/搜索