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.master和node.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"]
启动
- 新建新用户
adduser *** //添加用户
passwd *** //给用户赋值
- 用root用户执行
chown -R 用户名 elasticsearch安装文件夹
- 使用新用户启动
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包含三个plugin:input,filter,output。
安装
- 下载地址:https://www.elastic.co/downloads/logstash
- 复制mysql-connector-java-5.1.31.jar mysql驱动到logstash安装目录下。
- 在安装文件夹下创建配置文件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 总结
- es基本是开箱即用,非常简单。Solr安装略微复杂。
- Solr利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。
- 支持更多格式的数据,比如JS安装ON、XML、CSV,而 Elasticsearch 仅支持json文件格式。
- 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑。
- Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。
- Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高。