文章目录

  • mapping映射和高级语法查询DSL
    • 文档映射Mapping
      • 映射类型
      • 更改Mapping的字段类型
      • 常用Mapping参数配置
    • 批量操作
    • ES高级查询Query DSL
      • 查询所有match_all
      • 分页查询
      • 指定字段排序和指定字段返回
      • match
      • 多字段查询multi_match
      • 多字段查询query_string
      • 关键词查询Term
      • ES中的结构化搜索
      • 前缀查询prefix和通配符查询
      • 范围查询
      • 模糊查询fuzzy
      • 高亮highlight

mapping映射和高级语法查询DSL

文档映射Mapping

映射类型

Mapping类似数据库中的schema的定义,作用如下:

  • 定义索引中的字段的名称
  • 定义字段的数据类型,例如字符串,数字,布尔等
  • 字段,倒排索引的相关配置(Analyzer)

ES中Mapping映射可以分为动态映射和静态映射。
动态映射
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类 型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射
静态映射: 静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器 等,这种方式称之为静态映射

更改Mapping的字段类型

新增加字段
dynamic设为true时,一旦有新增字段的文档写入,Mapping 也同时被更新
dynamic设为false,Mapping 不会被更新,新增字段的数据无法被索引,但是信息会出现在_source中
dynamic设置成strict(严格控制策略),文档写入失败,抛出异常

PUT /user/
{"mappings":{"dynamic":"strict","properties" : {"address" : {"type" : "text"},"age" : {"type" : "long"},"name" : {"type" : "text"}} }
}
PUT /user/_doc/1
{"name":"张三","age":18,"address":"中国"
}
# 如果"dynamic"为true,province会更新到mapping中,可以被搜索
# 如果"dynamic"为false,province不会更新到mapping中,无法被搜索,但会在_source中展示
# 如果"dynamic"为strict,执行 PUT /user/_doc/2 会报错
PUT /user/_doc/2
{"name":"李四","age":18,"address":"中国福建厦门","province":"厦门"
}

对已有字段
一旦已经有数据写入,就不再支持修改字段定义。Lucene 实现的倒排索引,一旦生成后,就不允许修改如果希望改变字段类型,可以利用 reindex API,重建索引。因为:如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
但是如果是增加新的字段,就不会有这样的影响
那如何修改已有的字段,具体步骤
1)如果要推倒现有的映射, 你得重新建立一个静态索引
2)然后把之前索引里的数据导入到新的索引里
3)删除原创建的索引
4)为新索引起个别名, 为原索引名

#新建索引
PUT /user2/
{"mappings":{"properties" : {"address" : {"type" : "keyword"},"age" : {"type" : "long"},"name" : {"type" : "text","analyzer": "ik_max_word"}} }
}#将旧索引的数据复制到新索引中
POST _reindex
{"source": {"index": "user"},"dest": {"index": "user2"}
}
#删除旧索引
DELETE /user
# 给新索引设置别名
PUT /user2/_alias/user

通过这几个步骤就实现了索引的平滑过渡,并且是零停机

常用Mapping参数配置

index: 控制当前字段是否被索引,默认为true。如果设置为false,该字段不可被搜索
index options配置:有四种不同index options配置,控制倒排索引记录的内容:

  • docs : 记录doc id
  • freqs:记录doc id 和term frequencies(词频)
  • positions: 记录doc id / term frequencies / term position
  • offsets: doc id / term frequencies / term posistion / character offsets

text类型默认记录postions,其他默认为 docs。记录内容越多,占用存储空间越大
null_value: 需要对Null值进行搜索,只有keyword类型支持设计Null_Value
copy_to设置:将字段的数值拷贝到目标字段,满足一些特定的搜索需求。copy_to的目标字段不出现在_source中。

PUT /user2/
{"mappings":{"properties" : {"address" : {"type" : "keyword","index": false,"null_value": "NULL"},"age" : {"type" : "long"},"name" : {"type" : "text","analyzer": "ik_max_word","index_options": "docs"},"province" : {"type" : "keyword","copy_to": "full_address"},"city" : {"type" : "text","copy_to": "full_address"}}},"settings" : {"index" : {"analysis.analyzer.default.type": "ik_max_word"}}
}

批量操作

批量操作可以减少网络连接所产生的开销,提升性能

  • 支持在一次API调用中,对不同的索引进行操作
  • 可以再URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果

通过_bulk操作文档,一般至少有两行参数(或偶数行参数),第一行参数为指定操作的类型及操作的对象(index,type和id)
第二行参数才是操作的数据。
参数类似于:

{"actionName":{"_index":"indexName", "_type":"typeName","_id":"id"}}
{"field1":"value1", "field2":"value2"}

actionName:表示操作类型,主要有create,index,delete和update
批量创建文档create
批量对文档进行写操作是通过_bulk的API来实现的

POST _bulk
{"create":{"_index":"user","_id":1}}
{"id":1,"name":"张三","content":"张三的名称","tags":["java","面向对象"],"create_time":1554015482530}
{"create":{"_index":"user","_id":2}}
{"id":2,"title":"李四","content":"李四的名称","tags":["java","面向对象"],"create_time":1554015482530}

普通创建或全量替换index

POST _bulk
{"index":{"_index":"user","_id":1}}
{"id":1,"name":"张三","content":"张三的名称","tags":["java","面向对象"],"create_time":1554015482530}
{"index":{"_index":"user","_id":2}}
{"id":2,"title":"李四","content":"李四的名称","tags":["java","面向对象"],"create_time":1554015482530}

如果原文档不存在,则是创建
如果原文档存在,则是替换(全量修改原文档)

批量删除delete

POST _bulk
{"delete":{"_index":"user","_id":1}}
{"delete":{"_index":"user","_id":2}}

批量修改update

POST _bulk
{"update":{"_index":"user", "_id":1}}
{"doc":{"name":"张三111"}}
{"update":{"_index":"user", "_id":2}}
{"doc":{"name":"李四111"}}

ES高级查询Query DSL

ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL(Domain Specified Language) , Query DSL是利用Rest API传递JSON格式的请求体(RequestBody)数据与ES进行交互,这种方式的丰富查询语法让ES检索变得更强大,更简洁。语法:GET /es_db/_search {json请求体数据}
测试数据

PUT _bulk
{"create":{"_index":"es_db","_id":1}}
{"name": "张三","sex": 1,"age": 25,"address": "广州天河公园","remark": "java developer"}
{"create":{"_index":"es_db","_id":2}}
{"name": "李四","sex": 1,"age": 28,"address": "广州荔湾大厦","remark": "java assistant"}
{"create":{"_index":"es_db","_id":3}}
{"name": "王五","sex": 0,"age": 26,"address": "广州白云山公园","remark": "php developer"}
{"create":{"_index":"es_db","_id":4}}
{"name": "赵六","sex": 0,"age": 22,"address": "长沙橘子洲","remark": "python assistant"}
{"create":{"_index":"es_db","_id":5}}
{"name": "张龙","sex": 0,"age": 19,"address": "长沙麓谷企业广场","remark":"java architect assistant"}
{"create":{"_index":"es_db","_id":6}}
{"name": "赵虎","sex": 1,"age": 32,"address": "长沙麓谷兴工国际产业园","remark":"java architect"}
{"create":{"_index":"es_db","_id":7}}

查询所有match_all

使用match_all,默认只会返回10条数据。_search查询默认采用的是分页查询,每页记录数size的默认值为10。如果想显示更多数据,指定size

GET /es_db/_search
等同于
GET /es_db/_search
{"query":{"match_all":{}
}
#==================
}
GET es_db/_search
{"size":10001 #size默认最大1万条,超过会报错 可以通过参数配置
}
#设置查询结果的窗口的限制
PUT es_db/_settings
{"index.max_result_window" :"20000"
}

注意:参数index.max_result_window主要用来限制单次查询满足查询条件的结果窗口的大小,窗口大小由from + size共同决定。不能简单理解成查询返回给调用方的数据量。这样做主要是为了限制内存的消耗。

分页查询

from 关键字: 用来指定起始返回位置,和size关键字连用可实现分页效果

GET es_db/_search
{"size": 2,"from": 0
}

深分页查询Scroll
改动index.max_result_window参数值的大小,只能解决一时的问题,当索引的数据量持续增长时,在查询全量数据时还是会出现问题。而且会增加ES服务器内存大结果集消耗完的风险。最佳实践还是根据异常提示中的采用scroll api更高效的请求大量数据集。

#查询命令中新增scroll=1m,说明采用游标查询,保持游标查询窗口一分钟。
GET /es_db/_search?scroll=1m
{"size":  3
}
#scroll_id 的值就是上一个请求中返回的 _scroll_id 的值
#这里不需要指定size,第一次查询多少条,通过scroll返回的也是多少条
GET /_search/scroll
{"scroll": "1m", "scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFldmbm0tUkU3U0JPUUhUY0RST1Y1SmcAAAAAAABgnhZUTGlHdVB3MlEyeUU0d1VRTjNXd1F3"
}

多次根据scroll_id游标查询,直到没有数据返回则结束查询。采用游标查询索引全量数据,更安全高效,限制了单次对内存的消耗。

指定字段排序和指定字段返回

GET es_db/_search
{"from": 0,"size": 10,"sort": [{"age":  "desc"}], #指定排序会让得分失效"_source": ["name","sex","address"]
}

match

match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找。match支持以下参数:

query : 指定匹配的值
operator : 匹配条件类型
and : 条件分词后都要匹配
or : 条件分词后有一个匹配即可(默认)
minmum_should_match : 最低匹配度,即条件在倒排索引中最低的匹配度

#分词后or的效果
GET es_db/_search
{"query": {"match": {"address": "广州白云山公园"}}
}
#分词后and的效果
GET es_db/_search
{"query": {"match": {"address": {"query": "广州白云山公园","operator": "and"}}}
}
#分词后or的效果 但至少要满足2个任意的分词条件
GET es_db/_search
{"query": {"match": {"address": {"query": "广州白云山公园","operator": "or","minimum_should_match": 2}}}
}
#查看分词
GET _analyze
{"analyzer": "ik_max_word","text": "广州白云山公园"
}

多字段查询multi_match

可以根据字段类型,决定是否使用分词查询,得分最高的在前面

GET es_db/_search
{"query": {"multi_match": {"query": "长沙王五","fields": ["name","address"]}}
}

注意:字段类型分词,将查询条件分词之后进行查询,如果该字段不分词就会将查询条件作为整体进行查询。

多字段查询query_string

允许我们在单个查询字符串中指定AND | OR | NOT条件,同时也和 multi_match query 一样,支持多字段搜索。和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
注意: 查询字段分词就将查询条件分词查询,查询字段不分词将查询条件不分词查询

#未指定字段查询
GET /es_db/_search
{"query": {"query_string": {"default_field": "address","query": "白云山 OR 橘子洲"}}
}#未指定字段查询
GET es_db/_search
{"query": {"query_string": {"query": "张三 OR 橘子洲"}}
}#指定多字段查询
GET /es_db/_search
{"query": {"query_string": {"fields": ["name","address"],"query": "张三 OR 橘子洲"}}
}

关键词查询Term

Term用来使用关键词查询(精确匹配),还可以用来查询没有被进行分词的数据类型。Term是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term。match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般模糊查找的时候,多用match,而精确查找时可以使用term
在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分词,只有text类型分词。

# 查不到数据 因为倒排索引中没有广白云山公园
GET es_db/_search
{"query": {"term": {"address": {"value": "广白云山公园"}}}
}
# 可以查到数据 通过keyword 映射到address字段不进行分词
# 相当于mapping中的address的类型是keyword
GET /es_db/_search
{"query":{"term": {"address.keyword": {"value": "广州白云山公园"}}}

在ES中,Term查询,对输入不做分词。会将输入作为一个整体,在倒排索引中查找准确的词项,并且使用相关度算分公式为每个包含该词项的文档进行相关度算分。

PUT /product/_bulk
{"index":{"_id":1}}
{"productId":"xxx123","productName":"iPhone"}
{"index":{"_id":2}}
{"productId":"xxx111","productName":"iPad"}# 思考: 查询iPhone可以查到数据吗?
GET /product/_search
{"query":{"term": {"productName": {"value": "iPhone"}}}
}

对于英文分词会将大写转成小写,可以考虑建立索引时忽略大小写

PUT /product
{"settings": {"analysis": {"normalizer": {"aaa": {"filter": ["lowercase","asciifolding"],"type": "custom"}}}},"mappings": {"properties": {"productId": {"type": "text"},"productName": {"type": "keyword","normalizer": "aaa","index": "true"}}}
}

可以通过 Constant Score 将查询转换成一个 Filtering,避免算分,并利用缓存,提高性能。

  • 将Query 转成 Filter,忽略TF-IDF计算,避免相关性算分的开销
  • Filter可以有效利用缓存
GET es_db/_search
{"query": {"constant_score": {"filter": {"term": {"address.keyword": "广州白云山公园"}}}}
}

ES中的结构化搜索

结构化搜索(Structured search)是指对结构化数据的搜索。
结构化数据:

  • 日期,布尔类型和数字都是结构化的
  • 文本也可以是结构化的。
    如彩色笔可以有离散的颜色集合:红(red) 、绿(green、蓝(blue)
    一个博客可能被标记了标签,例如,分布式(distributed)和搜索(search)
    电商网站上的商品都有UPC(通用产品码Universal Product Code)或其他的唯一标识,它们都需要遵从严格规定的、结构化的格式。
    应用场景:对bool,日期,数字,结构化的文本可以利用term做精确匹配
GET /es_db/_search
{"query": {"term": {"age": {"value": 28}}}
}POST /employee/_bulk
{"index":{"_id":1}}
{"name":"小明","interest":["跑步","篮球"]}
{"index":{"_id":2}}
{"name":"小红","interest":["跳舞","画画"]}
{"index":{"_id":3}}
{"name":"小丽","interest":["跳舞","唱歌","跑步"]}
#term处理多值字段,term查询是包含,不是等于
POST /employee/_search
{"query": {"term": {"interest.keyword": {"value": "跑步"}}}
}

前缀查询prefix和通配符查询

前缀查询
它会对分词后的倒排索引进行前缀搜索。
它不会分析要搜索字符串,传入的前缀就是想要查找的前缀
默认状态下,前缀查询不做相关度分数计算,它只是将所有匹配的文档返回,然后赋予所有相关分数值为1。它的行为更像是一个过滤器而不是查询。两者实际的区别就是过滤器是可以被缓存的,而前缀查询不行。
prefix的原理:需要遍历所有倒排索引,并比较每个term是否已所指定的前缀开头。

GET /es_db/_search
{"query": {"prefix": {"address": {"value": "广州"}}}
}

通配符查询
工作原理和prefix相同,只不过它不是只比较开头,它能支持更为复杂的匹配模式。

GET /es_db/_search
{"query": {"wildcard": {"address": {"value": "*白*"}}}
}

范围查询

range:范围关键字
gte 大于等于
lte 小于等于
gt 大于
lt 小于
now 当前时间

POST /es_db/_search
{"query": {"range": {"age": {"gte": 25,"lte": 28}}}
}
#=========时间范围查询==========
DELETE /product
POST /product/_bulk
{"index":{"_id":1}}
{"price":100,"date":"2021-01-01","productId":"XHDK-1293"}
{"index":{"_id":2}}
{"price":200,"date":"2022-01-01","productId":"KDKE-5421"}
GET /product/_search
{"query": {"range": {"date": {"gte": "now-2y"}}}
}
#多id查询
GET /es_db/_search
{"query": {"ids": {"values": [1,2]}}
}

模糊查询fuzzy

在实际的搜索中,我们有时候会打错字,从而导致搜索不到。在Elasticsearch中,我们可以使用fuzziness属性来进行模糊查询,从而达到搜索有错别字的情形。
fuzzy 查询会用到两个很重要的参数,fuzziness,prefix_length

fuzziness:表示输入的关键字通过几次操作可以转变成为ES库里面的对应field的字段
操作是指:新增一个字符,删除一个字符,修改一个字符,每次操作可以记做编辑距离为1,如中文集团到中威集团编辑距离就是1,只需要修改一个字符;该参数默认值为0,即不开启模糊查询。
如果fuzziness值在这里设置成2,会把编辑距离为2的东东集团也查出来。

prefix_length:表示限制输入关键字和ES对应查询field的内容开头的第n个字符必须完全匹配,不允许错别字匹配
如这里等于1,则表示开头的字必须匹配,不匹配则不返回
默认值也是0
加大prefix_length的值可以提高效率和准确率。

GET /es_db/_search
{"query": {"fuzzy": {"address": {"value": "白运山","fuzziness": 1    }}}
}GET /es_db/_search
{"query": {"match": {"address": {"query": "广洲","fuzziness": 1}}}
}

注意: fuzzy 模糊查询 最大模糊错误 必须在0-2之间
搜索关键词长度为 2,不允许存在模糊
搜索关键词长度为3-5,允许1次模糊
搜索关键词长度大于5,允许最大2次模糊

高亮highlight

highlight 关键字: 可以让符合条件的文档中的关键词高亮。
highlight相关属性:
pre_tags 前缀标签
post_tags 后缀标签
tags_schema 设置为styled可以使用内置高亮样式
require_field_match 多字段高亮需要设置为false

示例数据

#指定ik分词器
PUT /products
{"settings" : {"index" : {"analysis.analyzer.default.type": "ik_max_word"}}
}
PUT /products/_doc/1
{"proId" : "2","name" : "牛仔男外套","desc" : "牛仔外套男装春季衣服男春装夹克修身休闲男生潮牌工装潮流头号青年春秋棒球服男 7705浅蓝常规 XL","timestamp" : 1576313264451,"createTime" : "2019-12-13 12:56:56"
}
PUT /products/_doc/2
{"proId" : "6","name" : "HLA海澜之家牛仔裤男","desc" : "HLA海澜之家牛仔裤男2019时尚有型舒适HKNAD3E109A 牛仔蓝(A9)175/82A(32)","timestamp" : 1576314265571,"createTime" : "2019-12-18 15:56:56"
}

测试

GET /products/_search
{"query": {"term": {"name": {"value": "牛仔"}}},"highlight": {"fields": {"*":{}}}
}

自定义高亮html标签
可以在highlight中使用pre_tags和post_tags

GET /products/_search
{"query": {"term": {"name": {"value": "牛仔"}}},"highlight": {"post_tags": ["</span>"], "pre_tags": ["<span style='color:red'>"],"fields": {"*":{}}}
}

多字段高亮

GET /products/_search
{"query": {"term": {"name": {"value": "牛仔"}}},"highlight": {"pre_tags": ["<font color='red'>"],"post_tags": ["<font/>"],"require_field_match": "false","fields": {"name": {},"desc": {}}}
}

Elasticsearch7.17 二:mapping映射和高级语法查询DSL相关推荐

  1. Python面试题大全(二):python高级语法

    目录 Python高级 元类 42.Python中类方法.类实例方法.静态方法有何区别? 43.遍历一个object的所有属性,并print每一个属性名? 44.写一个类,并让它尽可能多的支持操作符? ...

  2. 规则引擎Drools使用 第十二篇 Drools 的高级语法之RHS加强

    RHS部分是规则体的重要组成部分,当LHS部分的条件匹配成功后,对应的RHS部分就会触发执行.一般在RHS部分中需要进行业务处理. 在RHS部分Drools为我们提供了一个内置对象,名称就是drool ...

  3. 9.17 hive高级语法01

    hive高级语法 数据库(Database) 表的集合,HDFS中表现为一个文件夹 默认在hive.metastore.warehouse.dir属性目录下 如果没有指定数据库,默认使用default ...

  4. 谷歌搜索语法(二)高级语法

    Google搜索语法(二)高级语法 接上篇:谷歌搜索语法(一)基本语法 通过上一篇博客,我们介绍了google的基本搜索语法,在生活中合理的运用这些搜索语法就可以协助我们更加精确.高效的找到我们想要的 ...

  5. Google搜索语法(二)高级语法

    Google搜索语法(二)高级语法 接上篇:谷歌搜索语法(一)基本语法 通过上一篇博客,我们介绍了google的基本搜索语法,在生活中合理的运用这些搜索语法就可以协助我们更加精确.高效的找到我们想要的 ...

  6. Gradle入门系列(二)——groovy高级语法

    groovy高级语法 一.json操作 使用groovy自带的json工具进行json操作 groovy.json.JsonSlurper:将json原数据转成实体对象 groovy.json.Jso ...

  7. ELK高级搜索四之Mapping映射和分词器

    Mapping映射入门 什么是mapping映射? 映射:创建索引的时候,可以预先定义字段的类型以及相关属性 elasticsearch会根据json源数据的基础类型猜测你想要的字段映射,将输入的数据 ...

  8. Elasticsearch7.17学习笔记

    前言 本学习笔记主要基于 阅读Elasticsearch7.17版本官方文档和实操总结而来,官方文档地址https://www.elastic.co/guide/en/elasticsearch/re ...

  9. 【强烈推荐】超详解Python-魔法函数(高级语法)

    Python-魔法函数(高级语法) 1. 前言 1.1 什么是魔法函数? 1.2 魔法函数有什么作用? 2. 常见的魔法函数 3. 非数学运算 3.1 字符串表示 `__repr__` `__str_ ...

最新文章

  1. iptables 入门
  2. android小程序案例_小程序案例赏析:高质量的小程序怎么做
  3. 电子漫画 - 轻轻松松
  4. 【基础】-设置VS2015开发环境
  5. 查找字符位置_Excel中查找字符第N次出现的位置信息,换个思路其实很简单
  6. 呆呆键盘手11.14号学到的定位-实现滚动门效果
  7. 集群状态正常时需要的jps进程+是否需要部署到各个节点(持续更新中)
  8. Micro-CMS v1
  9. 使用SAT研究IBASE hierarchy读取性能
  10. cpu高对计算机有什么影响吗,CPU损坏对电脑造成哪些影响
  11. hujingwei oracle_Oracle收缩表空间
  12. 猎豹浏览器截图在哪 猎豹浏览器如何截图
  13. 获取占用fd最大的前20个进程
  14. sql设为简单模式sql_SQL模式演练
  15. 在markdown (csdn)博客上输出 右下小标,右上小标。
  16. Spyder远程连接矩池云
  17. 大访问量网站缓存的一点思考,个人看法,勿拍砖
  18. java 模拟百度翻译
  19. viewstub学习笔记
  20. Opencv图像边缘检测——Roberts算子(手写)、Sobel算子(手写和调包)、Scharr算子、Laplacian算子

热门文章

  1. C中的struct,union,Bit Filed以及内存对齐
  2. apicloud常用方法总结
  3. 串口转以太网服务器原理,【干货】自制低成本串口转以太网网关
  4. 操作系统-逻辑地址转换为物理地址Java实现
  5. 推荐一个在线查看函数图象的网站 —— Desmos
  6. 云服务器 - 腾讯云主机信息
  7. 程序员的真实工资是多少?
  8. HDU-4539 郑厂长系列故事——排兵布阵 状态压缩DP Or 最大团
  9. 135微信编辑器html模式,135微信编辑器官网【设置思路】
  10. 协议分析(微信网页版 wx2.qq.com)