Elaticsearch笔记

ES用的比较多了,但没有系统学习,很多地方用得不科学,也踩了不少坑,比如滚动更新,扩大分片数等。

URL search

# 范查询
GET index/_search?q=A00001
# 指定字段查询
GET index/_search?q=billno:A00001,name:hugeo
# phrase 查询 要求url中有rule,有order,且rule在order前面
GET index/_search?q=billno:"rule order"
# 分组查询(Bool) + must  - must not    6.4不支持&& || !只支持 AND OR NOT
GET index/_search?q=url:(+rule -predict)
GET index/_search?q=url:(+rule && (+predict || -codpay))
# 范围查询
GET index/_search?q=pay_time:{* TO 157436254]

在kibana的dev tools里面写dsl其实也很快很方便,还有助于掌握ES查询语法,但是不得不承认,如果做一些简单的查询,或者在没有智能提示的地方,比如ratel,url search更快

ConstantScore

即使是keyword字段,即使是term查询,也会算分

分析器的组成

char filter:去除字符用的,比如去除html标签
tokenizer:分词器
token filter:过滤token,比如停用词,转小写等等

Dynamic Mappings

必备的配置,防止由于序列化的问题导致字段越来越多,影响集群性能

PUT index_name
{
	"mappings":{
		"_doc":{
			// 默认true,自动创建字段
			// false,存储值,但不创建字段,不可搜索
			// strict,有不认识的字段报错
			"dynamic":"false",
			// 字符串如果可以被转成数值,就以数值存储,默认false
			"numeric_detection": true,
			"date_detection": false,
			
		}
	}
}

Dynamic Template

es会自动新增mapping,而且是text类型,而且有个keyword子字段,被坑过,应该配合dynamic mappings进行控制

// match,unmatch 匹配字段名
// path_match path_unmatch 匹配字段路径(子字段)
// {name}和{dynamic_type}占位符在映射的时候会被替换为字段名称和检测到的动态类型
PUT index_name
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "custom": {
            "match_mapping_type": "string",
            "match":   "long_*",
            "unmatch": "*_text",
            "mapping": {
              "type": "long"
            }
          }
        }
      ]
    }
  }
}

_all再见,你好copy_to

SearchTemplate

SearchAfter 翻页

使用前,Query阶段,每个分片要返回From+Size个数据,使用后只需要返回Size个数据。
前提是sort的字段必须每个文档唯一,建议把_id加入即可。

查询

收到请求的节点,先routing,然后分发给目标节点
目标节点返回From+Size个_id和排序值
整个节点取出需要的,再根据_id去对应节点multiget取数据。
Query Then Fetch。对于exists的请求,能不要_source就不要配置。

倒排索引

不可变的好处:常驻缓存,无并发问题
倒排索引就是一个Segment,是不可变的,多个Segment组成一个Shard,也就是一个Lucene Index。

删除的文档再.del文件中

写入过程:

  1. 同时写入IndexBuffer(内存)和Translog(刷盘,每个Shard一个) ,此时不可查询
  2. 每次_refresh的时候,把IndexBuffer清空,写入Segment(仍是内存),可以查询了
  3. Flush默认30分钟一次,或者Translog达到512M了。先Refresh把Buffer清空,再把Segment刷盘。再清空Translog

字段的各种配置(心累)

  1. enable=false。只是召回,不用搜索排序聚合。原数据保存在_source
  2. index=false。不能搜索,可以聚合。原数据保存在_source
  3. 要搜索,不用排序和聚合的Keyword字段关闭DocValues
  4. text字段要排序和聚合,要打开field_data
  5. 对频繁聚合的字段开启eager_global_ordinals
  6. 只要不做range查询,即使是数值,也配置为keyword,可以提高查询性能
  7. 由于ES fetch阶段会自动传输_source数据,可以考虑整个mapping关闭_source。对于要保存原始数据的加上store=true,查询时指定stored_fields
  8. 字段为null可能影响平均值计算,使用null_value设置默认值

反范式设计

嵌套 Nested类型

查询性能高,更新不方便,一条船上的蚂蚱
查询时使用nested

父子 Join类型

方便更新,查询性能低,你是你,我是我
配套有parent_id,has_parent,has_child查询,父子文档必须在同一分片,子文档使用父文档的id做routing

聚合

Histogram高级版:Range聚合

聚合外面再做聚合

min_bucket

聚合的作用范围

query既限制hits,业限制聚合
聚合中的filter,只限制聚合
global 不受query限制

聚合可以配置按照_count或_key排序

Terms可能会不准确

每个分片取出自己term最多的项,实际上可能有的值太分散,结果没被选出来
结局办法:
数据量小就搞一个分片
多个分片时,配置shard_size大一些,可以从每个分片多取一些数据,性能下降

分布式计算难题

牺牲:
数据量:小数据实时计算
精准度:近似计算
实时性:离线计算

IngestNode & Pipeline

神器呀神器

Painless脚本

上下文 语法
Ingestion ctx.field_name
Update ctx._source.field_name
Search doc[“field_name”]

POST _script/script_name
类似search template的用法,使用script.id更新文档

你可能感兴趣的:(其他)