1 ES的基本信息
1基本概念:
Relational DB | Elasticsearch |
数据库(database) | 索引(indices) |
表(tables) | types |
行(rows) | documents |
字段(columns) | fields |
2 ES的适用和不适用场景
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 没有锁
3 Elasticsearch之settings和mappings的意义
简单的说,就是
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 该动态参数
以及自定义分词器 。
4 Es的字段类型
4.1 核心数据类型
(1)字符串类型: text, keyword
(2)数字类型:long
, integer
, short
, byte
, double
, float
, half_float
(3)日期:date
(4)日期 纳秒:date_nanos
(5)布尔型:boolean
(6)Binary:binary
。……
4.2 复杂数据类型
(1)Object: object(for single JSON objects)
(2)Nested: nested
(for arrays of JSON objects)
……
4.3 地理数据类型
(1)Geo-point: geo_point (for lat/lon points)
(2)Geo-shape: geo_shape (for complex shapes like polygons)
……
4.4 特殊数据类型
(1)IP: ip (IPv4 和 IPv6 地址)
(2)Completion类型:completion (to provide auto-complete suggestions)
……
4.5 Multi-fields
Multi-fields 通常用来以不同的方式或目的索引同一个字段。比如,一个字符串类型字段可以同时被映射为 text 类型以用于全文检索、 keyword字段用于排序或聚合。又或者,你可以用standard分析器、english分析器和french分析器来索引同一个 text字段。
分词器只对String类型起作用
字符串 - text:用于全文索引,该类型的字段将通过分词器进行分词,最终用于构建索引
字符串 - keyword:不分词,只能搜索该字段的完整的值,只用于 filtering
5 ES-分词器(Analyzer)
把输入的文本块按照一定的策略进行分解,并建立倒排索引。在Lucene的架构中,这个过程由分析器(analyzer)完成。
主要组成
- character filter:接收原字符流,通过添加、删除或者替换操作改变原字符流。例如:去除文本中的html标签,或者将罗马数字转换成阿拉伯数字等。一个字符过滤器可以有零个或者多个。
- tokenizer:简单的说就是将一整段文本拆分成一个个的词。例如拆分英文,通过空格能将句子拆分成一个个的词,但是对于中文来说,无法使用这种方式来实现。在一个分词器中,有且只有一个tokenizeer
- token filters:将切分的单词添加、删除或者改变。例如将所有英文单词小写,或者将英文中的停词a删除等。在token filters中,不允许将token(分出的词)的position或者offset改变。同时,在一个分词器中,可以有零个或者多个token filters.
内置的分析器:
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 | 用正则表达式处理字符串 |
有了这些就可以自定分析器。
6 索引和搜索分词
文本分词会发生在两个地方:
- 创建索引:当索引文档字符类型为text时,在建立索引时将会对该字段进行分词。
- 搜索:当对一个text类型的字段进行全文检索时,会对用户输入的文本进行分词。
配置分词器
默认ES使用standard analyzer,如果默认的分词器无法符合你的要求,可以自己配置。
https://console.bce.baidu.com/api/bes/kibana/461446499864285184/app/kibana#/dev_tools/console?_g=()