Relational DB |
Elasticsearch |
数据库(database) |
索引(indices) |
表(tables) |
types |
行(rows) |
documents |
字段(columns) |
fields |
2.1 ES适合的场景
1 检索。ES本身作为一个搜索引擎,用来处理检索的任务再合适不过。你可以在线上项目中直接将内容写入ES以提供检索服务,也可以把以往的数据导入ES以处理特定的需求。
2 统计。ES的统计也是基于检索功能的,聚合功能使得统计结果处理起来非常方便。如果你只需要统计而不用检索,可能有其他工具更适合你,比如Spark SQL。
2.2 ES不适合的场景
官网说:ES不是数据库,不是可靠的数据存储系统。
1 mapping不可改,不能改index属性。ES中以定义的mapping不能修改名字和属性,无法修改名字勉强还能接受,但无法修改属性。官方文档中介绍了几种修改mapping的方法。一个是新建一个字段,程序中所有地方修改名字,这对于复杂的项目容易出错,而且无法保留原来的数据;另一个是利用alias创建一个新的索引,但是所有数据需要重新导入,这需要很长时间,操作性不强。
2 无法多对多。ES中提供3种关联关系:Field collapsing(严格来说不是关联),Nested object,Parent-child。前两种都是直接将一个mapping声明在另一个mapping中,第三种关联是在创建子文档是指明他的父文档,但是一个子文档只能有一个父文档,因此也不能实现多对多的关联。其实如果理解了ES的目的是提升检索效率,就不难理解为什么没有多对多关联了,在关系数据库里这就是个效率瓶颈。
3 没有用户验证和权限控制。ES本身的访问权限可以通过nginx进行控制,但是同一个ES中不同索引间目前是没有权限控制的。
4 从ES设计的初衷看,为了检索,为了统计。这个从字段的store属性中可以看出来,查看ES手册(https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-store.html)可以发现,默认情况下字段的原始值是不会被保存的,这跟数据存储是南辕北辙了。
5 项目开始时不好确定shards数量。少了以后扩展不方便,多了一开始影响性能。这个可以通过将type命名为doctype-yyyymmdd来解决,每天都生成新的一个或多个shard,但是注意在搜索时需要在doctype-*中搜索。
ES非常适合特定的需求,但不适合用于数据存储。ES索引速度快,扩展方便,性能优异,但在功能上不适合作为数据库使用。数据存储的目的是为了以后能方便的使用,不仅是针对当前的需求,也要为未来可能出现的需求做准备。由于ES有以上几点问题,无法适应需求变化。
5 没有锁
简单的说,就是
settings是修改分片和副本数的。
mappings是修改字段和类型的。
简单理解 :mapping 是用来管理索引(index)中的内容的,setting是用来控制index整个的设置的。
Setting说明以及使用到的场景
索引的配置项按是否可以更改分为static属性与动态属性,所谓的静态配置即索引创建后不能修改。
静态属性 (简单了解即可)
index.number_of_shards: |
索引分片的数量。默认值5,ES支持的最大分片数默认为1024。 |
index.shard.check_on_startup: |
分片在打开之前是否检查该分片是否损坏。当检测到分片损坏时,将阻止打开。false:不检测,默认值;checksum:只检查物理结构;true:检查物理结构和路基损坏,相对比较消耗CPU |
index.codec: |
数据存储的压缩算法,默认值LZ4,可选值best_compression,比LZ4可以获得更好的压缩比例(占用较小的磁盘空间,但是存储性能比LZ4低)。 |
index.routing_partition_size: |
路由分区数,如果设置了该参数,其路由算法为:(hash(_routing) + hash(_id) % index.routing_parttion_size ) % number_of_shards;如果没有设置,路由算法为:hash(_routing) % number_of_shardings 其中_routing默认值为_id |
动态属性:(简单了解即可)
index.number_of_replicas |
索引复制分片的个数,默认值1,该值必须大于等于0,创建索引后该值可以变更。 |
index.auto_expand_replicas |
基于可用节点的数量自动分配副本数量,默认为 false(即禁用此功能),可设置为:0-all |
index.refresh_interval |
执行刷新操作的频率,该操作可以对索引的最新更改对搜索可见。默认1s。可以设置**-1**禁止刷新。 |
index.max_result_window |
控制分页搜索的总记录数,from+size的大小不能超过该值,默认为10000。 |
index.max_inner_result_window |
用于控制top aggregations,默认100。内部命中和顶部命中聚合占用堆内存,并且时间与from+size成正比,这限制了内存。 |
index.max_rescore_window |
在rescore搜索中,rescore请求的window_size的最大值。 |
index.max_docvalue_fields_search |
一次查询最多包含开启doc_values字段的个数,默认100。 |
index.max_script_fields |
查询中允许的最大script_fields数量。默认为32。 |
index.max_ngram_diff |
NGramTokenizer和NGramTokenFilter的min_gram和max_gram之间允许的最大差异。默认为1。 |
index.max_shingle_diff |
对于ShingleTokenFilter, max_shingle_size和min_shingle_size之间允许的最大差异。默认为3。 |
index.blocks.read_only |
索引数据、索引元数据是否只读,如果设置为true,则不能修改索引数据,也不能修改索引元数据。 |
index.blocks.read_only_allow_delete |
与index.blocks.read_only基本类似,唯一的区别是允许删除动作。 |
index.blocks.read |
设置为true以禁用对索引数据的读取操作。 |
index.blocks.write |
设置为true以禁用对索引数据的写操作。(针对索引数据,而不是索引元数据) |
index.blocks.metadata |
设置为true,表示不允许对索引元数据进行读与写。 |
index.max_refresh_listeners |
索引的每个分片上当刷新索引时最大的可用监听器数量。这些侦听器用于实现refresh=wait_for。 |
index.highlight.max_analyzed_offset |
高亮显示的最大字符数。此设置仅在对没有偏移或词向量的索引的文本上适用。默认情况下,此设置在6.x中未设置,默认为-1。 |
index.max_terms_count |
Term查询中可以使用的最大Term数。默认为65536。 |
index.routing.allocation.enable |
控制此索引的分片分配,可选值:all:默认,允许分片所有的分片;primaries:只允许分配主分片;new_primaries:仅允许分配新创建的主分片;none:不允许分配; |
index.routing.rebalance.enable |
允许分片重新平衡;primaries:只允许主分片重新平衡;replicas:只允许副本分片重新平衡;none:不允许分片重新平衡为此索引启用分片重新平衡, |
index.gc_deletes |
可选值:all:默认允许已删除文档的版本号,扔可用于进一步版本化操作的时间长度。默认60s。 |
index.max_regex_length |
Regexp Query中可以使用的正则表达式的最大长度,默认为1000。 |
mapping.coerce |
true:默认值,强制类型转换,把json中的值转为ES中字段的数据类型,譬如,把字符串"5"转为integer的5。false:当json的值与ES字段类型不匹配将会拒绝。 |
在这其中主要用到了 index.max_result_window 该动态参数
以及自定义分词器 。
(1)字符串类型: text, keyword
(2)数字类型:long
, integer
, short
, byte
, double
, float
, half_float
(3)日期:date
(4)日期 纳秒:date_nanos
(5)布尔型:boolean
(6)Binary:binary
。……
(1)Object: object(for single JSON objects)
(2)Nested: nested
(for arrays of JSON objects)
……
(1)Geo-point: geo_point (for lat/lon points)
(2)Geo-shape: geo_shape (for complex shapes like polygons)
……
(1)IP: ip (IPv4 和 IPv6 地址)
(2)Completion类型:completion (to provide auto-complete suggestions)
……
Multi-fields 通常用来以不同的方式或目的索引同一个字段。比如,一个字符串类型字段可以同时被映射为 text 类型以用于全文检索、 keyword字段用于排序或聚合。又或者,你可以用standard分析器、english分析器和french分析器来索引同一个 text字段。
分词器只对String类型起作用
字符串 - text:用于全文索引,该类型的字段将通过分词器进行分词,最终用于构建索引
字符串 - keyword:不分词,只能搜索该字段的完整的值,只用于 filtering
把输入的文本块按照一定的策略进行分解,并建立倒排索引。在Lucene的架构中,这个过程由分析器(analyzer)完成。
主要组成
内置的分析器:
analyzer |
logical name |
description |
standard analyzer |
standard |
standard tokenizer, standard filter, lower case filter, stop filter |
simple analyzer |
simple |
lower case tokenizer |
stop analyzer |
stop |
lower case tokenizer, stop filter |
keyword analyzer |
keyword |
不分词,内容整体作为一个token(not_analyzed) |
pattern analyzer |
whitespace |
正则表达式分词,默认匹配\W+ |
language analyzers |
lang |
各种语言 |
snowball analyzer |
snowball |
standard tokenizer, standard filter, lower case filter, stop filter, snowball filter |
custom analyzer |
custom |
一个Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter |
内置的分词器
tokenizer |
logical name |
description |
standard tokenizer |
standard |
|
edge ngram tokenizer |
edgeNGram |
|
keyword tokenizer |
keyword |
不分词 |
letter analyzer |
letter |
按单词分 |
lowercase analyzer |
lowercase |
letter tokenizer, lower case filter |
ngram analyzers |
nGram |
|
whitespace analyzer |
whitespace |
以空格为分隔符拆分 |
pattern analyzer |
pattern |
定义分隔符的正则表达式 |
uax email url analyzer |
uax_url_email |
不拆分url和email |
path hierarchy analyzer |
path_hierarchy |
处理类似/path/to/somthing样式的字符串 |
ES内置的token filter
token filter |
logical name |
description |
standard filter |
standard |
|
ascii folding filter |
asciifolding |
|
length filter |
length |
去掉太长或者太短的 |
lowercase filter |
lowercase |
转成小写 |
ngram filter |
nGram |
|
edge ngram filter |
edgeNGram |
|
porter stem filter |
porterStem |
波特词干算法 |
shingle filter |
shingle |
定义分隔符的正则表达式 |
stop filter |
stop |
移除 stop words |
word delimiter filter |
word_delimiter |
将一个单词再拆成子分词 |
stemmer token filter |
stemmer |
|
stemmer override filter |
stemmer_override |
|
keyword marker filter |
keyword_marker |
|
keyword repeat filter |
keyword_repeat |
|
kstem filter |
kstem |
|
snowball filter |
snowball |
|
phonetic filter |
phonetic |
插件 |
synonym filter |
synonyms |
处理同义词 |
compound word filter |
dictionary_decompounder, hyphenation_decompounder |
分解复合词 |
reverse filter |
reverse |
反转字符串 |
elision filter |
elision |
去掉缩略语 |
truncate filter |
truncate |
截断字符串 |
unique filter |
unique |
|
pattern capture filter |
pattern_capture |
|
pattern replace filte |
pattern_replace |
用正则表达式替换 |
trim filter |
trim |
去掉空格 |
limit token count filter |
limit |
限制token数量 |
hunspell filter |
hunspell |
拼写检查 |
common grams filter |
common_grams |
|
normalization filter |
arabic_normalization, persian_normalization |
ES内置的character filter
character filter |
logical name |
description |
mapping char filter |
mapping |
根据配置的映射关系替换字符 |
html strip char filter |
html_strip |
去掉HTML元素 |
pattern replace char filter |
pattern_replace |
用正则表达式处理字符串 |
有了这些就可以自定分析器。
文本分词会发生在两个地方:
配置分词器
默认ES使用standard analyzer,如果默认的分词器无法符合你的要求,可以自己配置。
https://console.bce.baidu.com/api/bes/kibana/461446499864285184/app/kibana#/dev_tools/console?_g=()