elasticsearch通过logstash同步mysql数据(中文分词)

本文详细介绍了Elasticsearch的架构、索引、文档、倒排索引等核心概念,涵盖安装、配置、查询语句、分词器使用,以及与Kibana、Logstash的集成方法,对比了Elasticsearch与Solr的优缺点。
摘要由CSDN通过智能技术生成

Elasticsearch

目录

概述

索引(Index)

类型(Type)

文档(Document)

倒排索引(Inverted Index)

节点(Node)

安装

启动

DSL(查询语句)

官方文档

查询语句的结构

创建索引

查询所有索引

删除索引

查看索引的mapping和setting

查询所有索引中数据

查询权重(boost)

复合查询示例(bool)

分词器(analyzer)

默认分词器

Ik分词器

Kibana

概述

安装

启动

访问

TransportClient

概述

核心依赖包

连接elasticsearch

连接client

执行语句

关闭连接

Logstash

概述

安装

配置文件详解

时区问题的解释

表结构

配置文件官方文档

启动

自定义模板

模板获取

动态模板创建

查看模板是否生效

Solr与ElasticSearch


概述

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官网https://www.elastic.co/

ElasticSearch6.0版本以上需要jdk8环境才可以运行。Linux系统中ElasticSearch不能以root用户启动。

索引(Index

ES将数据存储于一个或多个索引中,索引是具有类似特性的文档的集合。类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库,或者一个数据存储方案(schema)。索引由其名称(必须为全小写字符)进行标识,并通过引用此名称完成文档的创建、搜索、更新及删除操作。一个ES集群中可以按需创建任意数目的索引。

类型(Type

类型是索引内部的逻辑分区(category/partition),然而其意义完全取决于用户需求。因此,一个索引内部可定义一个或多个类型(type)。一般来说,类型就是为那些拥有相同的域的文档做的预定义。例如,在索引中,可以定义一个用于存储用户数据的类型,一个存储日志数据的类型,以及一个存储评论数据的类型。类比传统的关系型数据库领域来说,类型相当于

文档(Document

文档是索引和搜索的原子单位,它是包含了一个或多个域(Field)的容器,基于JSON格式进行表示。文档由一个或多个域组成,每个域拥有一个名字及一个或多个值,有多个值的域通常称为多值域。每个文档可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。

倒排索引(Inverted Index

每一个文档都对应一个ID。倒排索引会按照指定语法对每一个文档进行分词,然后维护一张表,列举所有文档中出现的terms以及它们出现的文档ID和出现频率。搜索时同样会对关键词进行同样的分词分析,然后查表得到结果。 这里所述倒排索引是针对非结构化的文档构造的,而在ES中存储的文档是基于JSON格式的,因此索引结构会更为复杂。简单来说,ES对于JSON文档中的每一个field都会构建一个对应的倒排索引。参考官方文档。

节点(Node

一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同cluster.name配置的节点组成, 它们共同承担数据和负载的压力。

ES集群中的节点有三种不同的类型:

  • 主节点:负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 主节点并不需要涉及到文档级别的变更和搜索等操作。可以通过属性node.master进行设置。
  • 数据节点:存储数据和其对应的倒排索引。默认每一个节点都是数据节点(包括主节点),可以通过node.data属性进行设置。
  • 协调节点:如果node.masternode.data属性均为false,则此节点称为协调节点,用来响应客户请求,均衡每个节点的负载。

安装

下载路径https://www.elastic.co/downloads/elasticsearch

修改配置文件/elasticsearch/conf/elasticsearch.yum

node.name: node-1

# ----------------------------------- Paths ------------------------------------

path.data: /opt/elk/data

# Path to log files:

path.logs: /opt/elk/logs

# ----------------------------------- Memory -----------------------------------

bootstrap.memory_lock: false

bootstrap.system_call_filter: false

# ---------------------------------- Network -----------------------------------

network.host: 0.0.0.0

http.port: 9200

# --------------------------------- Discovery ----------------------------------

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

启动

  1. 新建新用户

adduser ***   //添加用户

passwd ***  //给用户赋值

  1. 用root用户执行

chown -R 用户名 elasticsearch安装文件夹

  1. 使用新用户启动

nohup /usr/local/elasticsearch-6.4.0/bin/elasticsearch &

exit

DSL(查询语句)

官方文档

https://www.elastic.co/guide/en/elasticsearch/guide/2.x/query-dsl-intro.html

查询语句的结构

一个查询语句 的典型结构:
{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}
如果是针对某个字段,那么它的结构如下:
{
    QUERY_NAME: {
        FIELD_NAME: {
            ARGUMENT: VALUE,
            ARGUMENT: VALUE,...
        }
    }
}
举个例子,你可以使用 match 查询语句 来查询 tweet 字段中包含 elasticsearch 的 tweet:
{
    "match": {
        "tweet": "elasticsearch"
    }
}
完整的查询请求如下:
GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}

创建索引

curl -XPUT http://localhost:9200/indexname

查询所有索引

GET _cat/indices?v

删除索引

DELETE /indexname?pretty

查看索引的mapping和setting

GET /my_index_name?pretty

查询所有索引中数据

GET /_search

{

  "query": {

    "query_string" : {

        "query": "促销活动"

    }

  }

}

/_search:所有索引,所有type下的所有数据都搜索出来

/index1/_search:指定一个index,搜索其下所有type的数据

/index1,index2/_search:同时搜索两个index下的数据

/*1,*2/_search:按照通配符去匹配多个索引

/index1/type1/_search:搜索一个index下指定的type的数据

/index1/type1,type2/_search:可以搜索一个index下多个type的数据

/index1,index2/type1,type2/_search:搜索多个index下的多个type的数据

/_all/type1,type2/_search:_all,可以代表搜索所有index下的指定type的数据

查询权重(boost)

DSL语句:字段field加^权重值。

Java client:通过api提供的方法设置boost。

public org.elasticsearch.index.query.MultiMatchQueryBuilder fields(java.util.Map<java.lang.String,java.lang.Float> fields)

复合查询示例(bool)

​
POST /index_*/_search

{

         "query": {

                   "bool": {

                            "must": [{

                                     "multi_match": {

                                               "query": "鞋子",

                                               "fields": ["activity_address^1.0", "activity_context^1.0"],

                                               "type": "best_fields",

                                               "operator": "OR",

                                               "slop": 0,

                                               "prefix_length": 0,

                                               "max_expansions": 50,

                                               "zero_terms_query": "NONE",

                                               "auto_generate_synonyms_phrase_query": true,

                                               "fuzzy_transpositions": true,

                                               "boost": 1.0

                                     }

                            }],

                            "must_not": [{

                                     "match": {

                                               "disabled": {

                                                        "query": 1,

                                                        "operator": "OR",

                                                        "prefix_length": 0,

                                                        "max_expansions": 50,

                                                        "fuzzy_transpositions": true,

                                                        "lenient": false,

                                                        "zero_terms_query": "NONE",

                                                        "auto_generate_synonyms_phrase_query": true,

                                                        "boost": 1.0

                                               }

                                     }

                            }],

                            "should": [{

                                     "match": {

                                               "is_open": {

                                                        "query": 1,

                                                        "operator": "OR",

                                                        "prefix_length": 0,

                                                        "max_expansions": 50,

                                                        "fuzzy_transpositions": true,

                                                        "lenient": false,

                                                        "zero_terms_query": "NONE",

                                                        "auto_generate_synonyms_phrase_query": true,

                                                        "boost": 1.0

                                               }

                                     }

                            }],

                            "adjust_pure_negative": true,

                            "minimum_should_match": "1",

                            "boost": 1.0

                   }

         }

}

​

分词器(analyzer)

全文搜索引擎会用某种算法对要建索引的文档进行分析, 从文档中提取出若干Token(词元), 这些算法称为Tokenizer(分词器);这些Token会被进一步处理, 比如转成小写等, 这些处理算法被称为Token Filter(词元处理器), 被处理后的结果被称为Term(词), 文档中包含了几个这样的Term被称为Frequency(词频)。 引擎会建立Term和原文档的Inverted Index(倒排索引), 这样就能根据Term很快到找到源文档了。 文本被Tokenizer处理前可能要做一些预处理, 比如去掉里面的HTML标记, 这些处理的算法被称为Character Filter(字符过滤器), 这整个的分析算法被称为Analyzer(分析器)。

分词器需要在创建索引的时候就指定才可以使用。创建索引时使用standard分词器,而查询时使用ik分词是不生效的。

默认分词器

GET _analyze?pretty

{

  "analyzer": "standard",

  "text":"促销活动"

}

默认分词standard会把中文分成单个的字进行匹配。

​
{

  "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

    }

  ]

}

​

Ik分词器

下载地址https://github.com/medcl/elasticsearch-analysis-ik

安装方式参考github上教程。

Elasticsearch默认分词是把中文分成单个的字进行匹配,ik可以解决中文分词问题。

GET _analyze?pretty

{

  "analyzer": "ik_max_word",

  "text":"促销活动"

}

分词结果:

​
{

  "tokens": [

    {

      "token": "促销",

      "start_offset": 0,

      "end_offset": 2,

      "type": "CN_WORD",

      "position": 0

    },

    {

      "token": "活动",

      "start_offset": 2,

      "end_offset": 4,

      "type": "CN_WORD",

      "position": 1

    }

  ]

}

​

ik_max_word ik_smart 什么区别?

ik_max_word: 会将文本做最细粒度的拆分,比如会将中华人民共和国国歌拆分为中华人民共和国,中华人民,中华,华人,人民共和国,人民,,,共和国,共和,,国国,国歌,会穷尽各种可能的组合;

ik_smart: 会做最粗粒度的拆分,比如会将中华人民共和国国歌拆分为中华人民共和国,国歌

Kibana

概述

Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看、交互存放在Elasticsearch索引里的数据,使用各种不同的图表、表格、地图等kibana能够很轻易地展示高级数据分析与可视化。

安装

下载地址:https://www.elastic.co/downloads/kibana

修改配置文件kibana/conf/kibana.yum

 

启动

         nohup /usr/local/kibana-6.4.0-linux-x86_64/bin/kibana > /nohub.out 2>&1 &

         exit

访问

http://localhost:5601

RestHighLevelClient

概述

         Java程序可以通过RestHighLevelClient连接elasticsearch,使用http协议,默认端口为9200。通过http连接elasticsearch服务更加安全,阿里云版本只开放了9200端口。

核心依赖包

<!-- Elasticsearch核心依赖包 -->

<dependency>

    <groupId>org.elasticsearch.client</groupId>

    <artifactId>elasticsearch-rest-high-level-client</artifactId>

</dependency>

获取client

private static RestHighLevelClient init(String user, String password, String host, Integer port) throws Exception {

    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();

    credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(user, password));

    RestHighLevelClient restHighClient = new RestHighLevelClient(RestClient.builder(new HttpHost(host,port,"http"))

        .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {

            @Override

            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {

                return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);

            }

        })

    );

    return restHighClient;

}

执行语句

//搜索请求

SearchRequest searchRequest = new SearchRequest();

//控制搜索行为

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

searchRequest.source(searchSourceBuilder);

SearchResponse res = null;

res = restHighClient.search(searchRequest);

关闭连接

client.close();

TransportClient(官方已经不建议使用)

概述

         Java程序可以通过TransportClient连接elasticsearch,使用tcp协议,默认端口为9300。这种连接方式不安全,官方已经弃用,阿里云版本无法使用9300端口。

核心依赖包

<!-- Elasticsearch核心依赖包 -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>6.4.0</version>
</dependency>

连接elasticsearch

Elasticsearch会开放两个端口,客户端client连接elasticsearch使用9300端口,http请求使用的是9200端口。

连接client

​
String host = "192.168.0.1";
int port = 9300; //http请求的端口是9200,客户端是9300
String cluster= "my-application";

TransportClient client = new PreBuiltTransportClient(settings).addTransportAddresses(new TransportAddress(InetAddress.getByName(host), port));

​

执行语句

​
QueryBuilder qb = QueryBuilders.queryStringQuery(query);

int from = 0;
int size = 25;
SearchResponse res = client.prepareSearch().setQuery(qb).setFrom(from).setSize(size).get();

​

关闭连接

​
client.close();

​

Logstash

概述

Logstash is an open source data collection engine with real-time pipelining capabilities

简单来说logstash就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端;与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供里很多功能强大的滤网以满足你的各种应用场景。

Logstash包含三个plugininput,filter,output

安装

  1. 下载地址:https://www.elastic.co/downloads/logstash
  2. 复制mysql-connector-java-5.1.31.jar mysql驱动到logstash安装目录下。
  3. 在安装文件夹下创建配置文件mysql.conf
​
input {



    jdbc{

          type => "index_a"



          #The path to our download jdbc driver

          jdbc_connection_string => "jdbc:mysql://192.168.0.1:3306/db"

          jdbc_driver_library => "/usr/local/logstash-6.4.0/mysqletc/mysql-connector-java-5.1.31.jar"

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



          #The user we wish to execute our statement as

          jdbc_user => "root"

          jdbc_password => "root"

          

          last_run_metadata_path => "/usr/local/logstash-6.4.0/mysqletc/logstash_jdbc_last_run_index_a"

          

          #every 5 minutes execute

          schedule => "*/3 * * * *"

          #schedule => "* * * * *"

          

          #if clean_run set to true, sql_last_value is set to 19700101

          #clean_run => true



          #out query

          #parameters => {"name" => ""}



          #statement => "select * from sys_user where name = :name"

          #statement => "select * from order_form where modify_time > :sql_last_value"

          statement => "select * from order_form where modify_time > :sql_last_value or create_time > :sql_last_value"



          record_last_run => true

          #use_column_value => true

          #tracking_column_type => "timestamp"

          #tracking_column => "modify_time"

     #lowercase_column_names => "false"



          #jdbc_paging_enabled => "true"

          #jdbc_page_size => "1000"



          jdbc_default_timezone =>"Asia/Shanghai"

         }

        

         jdbc{

          type => "index_b"



          #The path to our download jdbc driver

          jdbc_connection_string => "jdbc:mysql://192.168.0.1:3306/db"

          jdbc_driver_library => "/usr/local/logstash-6.4.0/mysqletc/mysql-connector-java-5.1.31.jar"

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



          #The user we wish to execute our statement as

          jdbc_user => "root"

          jdbc_password => "root"

          

          last_run_metadata_path => "/usr/local/logstash-6.4.0/mysqletc/logstash_jdbc_last_run_index_b"

          

          #every 5 minutes execute

          schedule => "*/3 * * * *"

          #schedule => "* * * * *"

          

          #if clean_run set to true, sql_last_value is set to 19700101

          #clean_run => true



          #out query

          #parameters => {"name" => ""}



          statement => "select * from index_b where modifier_time > :sql_last_value or create_time > :sql_last_value"

          

          record_last_run => true

          #use_column_value => true

          #tracking_column_type => "timestamp"

          #tracking_column => "modifier_time"

          #lowercase_column_names => "false"



          #jdbc_paging_enabled => "true"

          #jdbc_page_size => "1000"



          jdbc_default_timezone =>"Asia/Shanghai"

         }

}





filter {

         json {

                   source => "message"

                   remove_field => ["message"]

         }

         #       ruby {code => "event.set('yearmonth',event.get('create_date').to_s[0..6])"}

         #       if "" in [document_id] {uuid {target => "document_id"}}

}





output {



   stdout{ codec => json_lines  }

   #stdout { codec => rubydebug }

  

#   elasticsearch{

#          "hosts" => "192.168.0.1:9200"

#          "index" => "%{type}"

#          "document_type" => "%{type}"

#          "document_id" => "%{id}"

#          doc_as_upsert => true

#          action => "update"

#   }

  

    if[type] == "index_a" {

        elasticsearch {

            hosts => ["192.168.0.1:9200"]

            index => "index_order_form"

            document_id => "%{id}"

                            template_overwrite => true

            template => "/usr/local/logstash-6.4.0/mysqletc/template2.json"

        }

    }

    if[type] == "index_b" {

        elasticsearch {

            hosts => ["192.168.0.1:9200"]

            index => "index_news_activity"

            document_id => "%{id}"

                            template_overwrite => true

            template => "/usr/local/logstash-6.4.0/mysqletc/template2.json"

        }

    }

}

​

配置文件详解

Jdbc:input里每个jdbc可以配置不同数据库和查询语句。

Type:对应elasticsearch中type。

Statement:sql查询语句。

record_last_run:true时,默认会把当前UTC时间存储到last_run_metadata_path文件中, use_column_value为true时将会把上次查询的最后一条记录的tracking_column值记录下来,保存到 last_run_metadata_path 指定的文件中。

use_column_value:是否使用最后一条数据的tracking_column值 track给sql_last_value。

tracking_column_type:选用的自定义字段的类型,可为"numeric"或"timestamp",默认数字。

tracking_column:选择的自定义字段名称,例如"modify_time"。

sql_last_value:放在statement sql语句where后面,比如自增id或者modify_time。

last_run_metadata_path:把上次查询数据的标识放到文件里,文件的路径。

clean_run:为true,每次启动logstash,last_run_metadata_path存储的时间初始化19700101。

input里每个jdbc可以配置不同数据库和查询语句,并且可以设置间隔多长时间执行一次查询语句,默认每60秒执行一次sql语句。

output中设置elasticsearch路径和对应索引,同一个索引index中不能存在不同的type。Column_id对应elasticsearch检索数据中的_id字段,elasticsearch通过这个id来判断新增还是修改数据。如果同一个index中已经存在该id的数据,则把该数据替换为最新的,如果index中还没有该id的数据就在索引中新增一条。如果希望logstash能够自动把修改的数据同步到elasticsearch,那么需要从input中配置的sql语句着手。确保mysql中数据修改了以后,input中设置的sql语句可以查询到该条数据。只要该数据column_id不变就可以更新到elasticsearch上。每次都查询整个表是最匹配的办法,但是数据量过大时mysql负担会很大。通过where语句配合sql_last_value可以过滤掉旧数据只更新最近修改的数据。

sql_last_value默认取linux当前系统时间,然后记录到last_run_metadata_path 指定的日志文件中。如果use_column_value为true,则会记录当前查询数据中最后一条数据对应的tracking_column值。比如说tracking_column=>id,则会把查询的最后一条数据id记录到日志文件中,下次在查询时可以在where语句中把id小于日志中id的值全部过滤掉,实现增量同步到elasticsearch。大多数情况下使用linux当前时间配合表字段modify_time就可以实现增量同步。

删除的数据可通过sql查询语句中is_deleted字段过滤掉,物理删除的数据无法同步,只能通过elasticsearch客户端指定id来删除该条数据。

时区问题的解释

很多中国用户经常提一个问题:为什么 @timestamp 比我们早了 8 个小时?怎么修改成北京时间?

其实,Elasticsearch 内部,对时间类型字段,是统一采用 UTC 时间,存成 long 长整形数据的!对日志统一采用 UTC 时间存储,是国际安全/运维界的一个通识——欧美公司的服务器普遍广泛分布在多个时区里——不像中国,地域横跨五个时区却只用北京时间。 

对于页面查看,ELK 的解决方案是在 Kibana 上,读取浏览器的当前时区,然后在页面上转换时间内容的显示。 

所以,建议大家接受这种设定。否则,即便你用 .getLocalTime 修改,也还要面临在 Kibana 上反过去修改,以及 Elasticsearch 原有的 ["now-1h" TO "now"] 这种方便的搜索语句无法正常使用的尴尬。以上,请读者自行斟酌。

表结构

和logstash最匹配的表结构应该具备以下特性:

唯一标识符字段:logstash用来匹配索引中的数据。如果无唯一标识符会产生相同的数据。

修改时间字段:查询时过滤未修改的数据,无需每次都查询所有数据减轻数据库压力。

删除字段:可以用来过滤删除的数据,如果使用物理删除,logstash中无法同步。

Elasticsearch6.0开始弃用type属性。所以在logstash里面index对应db数据库,type对应表的方式不在适用。应该改为一个index对应一个表,查询时通过跨index查询多个表中数据。

配置文件官方文档

Input plugin

https://www.elastic.co/guide/en/logstash/6.4/plugins-inputs-jdbc.html

Output plugin

https://www.elastic.co/guide/en/logstash/6.4/plugins-outputs-elasticsearch.html

Filter plugin

https://www.elastic.co/guide/en/logstash/6.4/plugins-filters-elasticsearch.html

启动

nohup logstash-6.4.0/bin/logstash -f /logstash-6.4.0/mysqletc/mysql2_1.conf &

exit

自定义模板

ES导入数据必须先创建index,mapping,但是在logstash中并没有直接创建,我们只传入了index,type等参数,logstash是通过es的mapping template来创建的,这个模板文件不需要指定字段,就可以根据输入自动生成。

Elasticsearch安装了ik分词器插件,logstash采集mysql数据以后默认通过Elasticsearch模板创建索引文件,默认模板创建索引文件时使用默认分词器并没有使用ik分词器,导致通过ik_max_word查询数据时数据错乱。可先创建自定义模板,在模板中指定索引index和ik分词器,然后在logstash output中指定这个模板。

动态模板(dynamic_templates) 可以做到对某种类型字段进行匹配mapping。

需要注意的是,模板json文件中需要使用template指定索引名称,匹配不上的索引就会使用默认模板创建,默认模板使用standard分词器。分词器需要在创建索引的时候就指定才可以使用。创建索引时使用standard分词器,而查询时使用ik分词是不生效的。

模板获取

通过logstash启动时打印的日志可以获取logstash默认使用的模板。

 

动态模板创建

1. 切换路径  cd  /usr/local/logstash 目录下

2. 新建template目录 mkdir template

3. cd template

4. 新建文件 logstash-ik.json  

5. 编辑文件内容

(只适用5.4.4版本):

{

    "template": "*",

    "version": 50001,

    "settings": {

        "index.refresh_interval": "5s"

    },

    "mappings": {

        "_default_": {

            "_all": {

                "enabled": true,

                "norms": false

            },

            "dynamic_templates": [

                {

                    "message_field": {

                        "path_match": "message",

                        "match_mapping_type": "string",

                        "mapping": {

                            "type": "text",

                            "norms": false

                        }

                    }

                },

                {

                    "string_fields": {

                        "match": "*",

                        "match_mapping_type": "string",

                        "mapping": {

                            "type": "text",

                            "norms": false,

                            "analyzer": "ik_max_word",

                            "fields": {

                                "keyword": {

                                    "type": "keyword"

                                }

                            }

                        }

                    }

                }

            ],

            "properties": {

                "@timestamp": {

                    "type": "date",

                    "include_in_all": false

                },

                "@version": {

                    "type": "keyword",

                    "include_in_all": false

                }

            }

        }

    }

}

(只适用6.4.0版本):

{

         "template": "index_*",

         "version": 60001,

         "settings": {

                   "index.refresh_interval": "5s"

         },

         "mappings": {

                   "_default_": {

                            "dynamic_templates": [{

                                     "message_field": {

                                               "path_match": "message",

                                               "match_mapping_type": "string",

                                               "mapping": {

                                                        "type": "text",

                                                        "norms": false

                                               }

                                     }

                            }, {

                                     "string_fields": {

                                               "match": "*",

                                               "match_mapping_type": "string",

                                               "mapping": {

                                                        "type": "text",

                                                        "norms": false,

                                                        "analyzer": "ik_max_word",

                                                        "fields": {

                                                                 "keyword": {

                                                                           "type": "keyword",

                                                                           "ignore_above": 256

                                                                 }

                                                        }

                                               }

                                     }

                            }],

                            "properties": {

                                     "@timestamp": {

                                               "type": "date"

                                     },

                                     "@version": {

                                               "type": "keyword"

                                     },

                                     "geoip": {

                                               "dynamic": true,

                                               "properties": {

                                                        "ip": {

                                                                 "type": "ip"

                                                        },

                                                        "location": {

                                                                 "type": "geo_point"

                                                        },

                                                        "latitude": {

                                                                 "type": "half_float"

                                                        },

                                                        "longitude": {

                                                                 "type": "half_float"

                                                        }

                                               }

                                     }

                            }

                   }

         }

}

6. 修改mysql.conf文件。

模板文件template.json中template需要和output中配置的index名称一致。template可以使用*配置任意字符。

output {

    elasticsearch {

        hosts => "127.0.0.1:9200"

        # index名

        # template.json中index_*可以匹配任意index_开头的索引

index => "index_es_define"

        # 需要关联的数据库中有有一个id字段,对应索引的id号

        document_id => "%{id}"

        template_overwrite => true

        template => "/usr/local/logstash-5.5.2/template/logstash-ik.json"

    }

    stdout {

        codec => json_lines

    }

}

查看模板是否生效

Elasticsearch中执行GET /index_name?pretty,查看索引的mapping,是否包含ik分词器。

{

  " index_name ": {

    "aliases": {},

    "mappings": {

      "doc": {

        "dynamic_templates": [

          {

            "message_field": {

              "path_match": "message",

              "match_mapping_type": "string",

              "mapping": {

                "norms": false,

                "type": "text"

              }

            }

          },

          {

            "string_fields": {

              "match": "*",

              "match_mapping_type": "string",

              "mapping": {

                "analyzer": "ik_max_word",

                "fields": {

                  "keyword": {

                    "ignore_above": 256,

                    "type": "keyword"

                  }

Solr与ElasticSearch

ElasticSearch vs Solr 总结

  1. es基本是开箱即用,非常简单。Solr安装略微复杂。
  2. Solr利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。
  3. 支持更多格式的数据,比如JS安装ONXMLCSV,而 Elasticsearch 仅支持json文件格式。
  4. 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑。
  5. Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。
  6. Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高。

https://i-blog.csdnimg.cn/blog_migrate/0f7bb6bd86e7cd53b7e53ecc9d390040.png

https://i-blog.csdnimg.cn/blog_migrate/27aedfe581b4f731f0261799f9b0c333.png

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值