文章目录

  • 一、SearchAPI
  • 二、Query DSL
    • 2.1 基本语法格式
    • 2.2 匹配查询 match
    • 2.3 模糊查询&分页查询
    • 2.4 返回部分字段 _source
    • 2.5 复合查询 bool
    • 2.6 结果过滤 filter
    • 2.7 非全文检索字段 term
    • 2.8 排序 sort
    • 2.9 高亮查询 highlight
    • 2.10 聚合查询 aggs
  • 三、映射 Mapping
    • 3.1 Mapping 简介
    • 3.2 Dynamic Mapping
    • 3.3 数据类型
    • 3.4 nested 扁平化数据问题
    • 3.5 表数据迁移
  • 四、分词
  • 五、Elasticsearch搜索原理

一、SearchAPI

ES支持两种基本方式检索∶

  1. 通过使用REST request URI发送搜索参数(uri+检索参数)
  2. 通过使用REST request body来发送它们(uri+请求体)

① URI

GET bank/_search?q=*&sort=account_number:asc

② 请求体

GET bank/_search
{"query": {"match_all": {}},"sort": [{"account_number": {"order": "desc"}}]
}

二、Query DSL

2.1 基本语法格式

Elasticsearch提供了一个可以执行查询的Json风格的 DSL (domain-specific language领域特定语言),这个被称为Query DSL,该查询语言非常全面。

  • 一个查询语句的典型结构
QUERY_NAME:{ARGUMENT: VALUE,ARGUMENT: VALUE,...
}
  • 如果是针对某个字段,那么它的结构如下:
l
QUERY_NAME:{FIELD_NAME: [ARGUMENT: VALUE,ARGUMENT: VALUE,...}
}

2.2 匹配查询 match

基本数据类型(非字符串会精确匹配),字符串会分词匹配。

使用match_phrase不进行分词。

GET bank/_search
{"query": {"match": {"lastname": "Barron"}}
}

说明:使用multi_match表示多字段满足其一即返回结果。

GET bank/_search
{"query": {"multi_match": {"query": "mill", "fields": ["state","address"]}}
}

2.3 模糊查询&分页查询

GET bank/_search
{"query": {"fuzzy": {"city": "Lopezo"}},"from": 0,"size": 1
}

2.4 返回部分字段 _source

GET bank/_search
{"query": {"match": {"lastname": "Barron"}},"_source": "{firstname,lastname}"
}

2.5 复合查询 bool

mustmust not的条件必须一致,should不要求一致,当时会影响相关得分。

GET bank/_search
{"query": {"bool": {"must": [{"match": {"firstname": "Forbes"}}],"must_not": [{"match": {"firstname": "Jack"}}],"should": [{"match": {"age": "28"}}]}}
}

2.6 结果过滤 filter

filter不会计算相关性得分,只起过滤作用。

按照范围过滤如下:

GET bank/_search
{"query": {"bool": {"must": [{"match": {"firstname": "Forbes"}}],"filter": {"range": {"age": {"gte": 10,"lte": 30}}}}}
}

2.7 非全文检索字段 term

match一样。匹配某个属性的值。全文检索字段用match,其他非text字段匹配用term

GET bank/_search
{"query": {"term": {"age": "28"}}
}

2.8 排序 sort

GET bank/_search
{"query": {"match_all": {}},"sort": [{"account_number": {"order": "desc"}}]
}

2.9 高亮查询 highlight

GET bank/_search
{"query": {"match": {"lastname": "Bates"}},"highlight": {"fields": {"lastname":{}},"pre_tags": ["<span style='color:red'>"],"post_tags": ["</span>"]}
}

2.10 聚合查询 aggs

对查询结果进行聚合分析。field是聚合的字段,size代表预期的分类数

① 搜索address中包含mill的所有人的年龄分布以及平均年龄

GET bank/_search
{"query": {"match": {"address": "mill"}},"aggs": {"ageAgg": {"terms": {"field": "age","size": 100}},"ageAvg": {"avg": {"field": "age"}}}
}

② 按照年龄聚合,并且请求这些年龄段的这些人的平均薪资

GET bank/_search
{"query": {"match_all": {}},"aggs": {"ageAgg": {"terms": {"field": "age","size": 100},"aggs": {"balanceAvg": {"avg": {"field": "balance"}}}}}
}

③ 查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资

GET bank/_search
{"query": {"match_all": {}},"aggs": {"ageAgg": {"terms": {"field": "age","size": 100},"aggs": {"genderAgg": {"terms": {"field": "gender.keyword","size": 2},"aggs": {"balanceAvg": {"avg": {"field": "balance"}}}},"balanceAvg2": {"avg": {"field": "balance"}}}}}
}

三、映射 Mapping

3.1 Mapping 简介

定义数据库中的表的结构的定义,通过mapping来控制索引存储数据的设置,不进行配置时,自动创建的mapping

作用:

  • 定义Index下的字段名(Field Name
  • 定义字段的类型,比如数值型、字符串型、布尔型等
  • 定义倒排索引相关的配置,比如documentId、记录position、打分等

创建Mapping:GET /china/_mapping

自定义Mapping:

PUT my_store
{"mappings":{"book":{"dynamic":false,     "properties":{        "title":{"type":"text", "index_options": "docs"},"content":{"type":"keyword", "index": true}}}}
}

属性说明:

① dynamic

  • true:允许自动新增字段(默认的配置)
  • false:不允许自动新增字段,但是文档可以正常写入,无法对字段进行查询操作
  • strict:文档不能写入(如果写入会报错)

② index

Index属性,控制当前字段是否索引,默认为true,即记录索引,false不记录,即不可以搜索,比如:手机号、身份证号等敏感信息,不希望被检索

③ Index_options

用于控制倒排索引记录的内容,有如下4中配置:

  • docs:只记录docid
  • freqs:记录docidterm frequencies(词频)
  • position:记录docidterm frequenciesterm position
  • Offsets:记录docidterm frequenciesterm positioncharacter offsets

text类型默认配置为position,其默认认为docs。记录的内容越多,占用的空间越大。

3.2 Dynamic Mapping

Elasticsearch依靠json文档字段类型来实现自动识别字段类型,支持的类型

JSON类型 es类型
null 忽略
boolean boolean
浮点类型 float
整数 long
object object
array 由第一个非null值的类型决定
string 匹配为日期则设为data类型(默认开启) 匹配为数字的话设为float或long类型(默认关闭) 设为text类型,并附带keyword的子字段

注意:mapping中的字段类型一旦设定后,禁止修改

原因:Lucene实现的倒排索引生成后不允许修改(提高效率)。如果要修改字段的类型,需要从新建立索引,然后做reindex操作

3.3 数据类型

① 核心数据类型

字符串型:textkeyword
数值型:longintegershortbytedoublefloathalf_floatscaled_float
日期类型:date
布尔类型:boolean
二进制类型:binary
范围类型:integer_rangefloat_rangelong_rangedouble_rangedate_range

② 复杂数据类型

数组类型:array
对象类型:object
嵌套类型:nested object

③ 地理位置数据类型

geo_point(点)、geo_shape(形状)

④ 专用类型

记录IP地址:ip
实现自动补全:completion
记录分词数:token_count
记录字符串hash值:murmur3

⑤ 多字段特性multi-fields

允许对同一个字段采用不同的配置,比如分词,例如对人名实现拼音搜索,只需要在人名中新增一个子字段为pinyin即可。

3.4 nested 扁平化数据问题

首先我们创建一个数据,并查看她的数据类型

PUT my_index/_doc/1
{"group" : "fans","user" : [ {"first" : "John","last" :  "Smith"},{"first" : "Alice","last" :  "White"}]
}GET my_index/_mapping


此时我们查询Alice Smith用户竟然能查出来。

原因如下:

解决这种问题我们需要使用nested类型,删除index重建创建index并查看数据类型

DELETE my_indexPUT my_index
{"mappings": {"properties": {"user": {"type": "nested" }}}
}GET my_index/_mapping


此时已经不会出现扁平化导致的问题。

案例:
表结构

PUT product
{"mappings": {"properties": {"attrs": {"type": "nested","properties": {"attrId": {"type": "long"},"attrName": {"type": "keyword","index": false,"doc_values": false},"attrValue": {"type": "keyword"}}}}}
}

查询语句

--错误
GET /product/_search
{"query": {"bool": {"filter": {"term": {"attrs.attrId": "1"}}}}
}
--正确
GET /product/_search
{"query": {"bool": {"filter": {"nested": {"path": "attrs","query": {"bool": {"must": [{"term": {"attrs.attrId": {"value": "1"}}}]}}}}}}
}

3.5 表数据迁移

POST _reindex
{"source": {"index": "fromTable"},"dest": {"index": "toTable"}
}

四、分词

分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在ElasticSsearch里面称为Analysis

分词机制:

  1. Character Filter:对原始文本进行处理,例:去除html标签、特殊字符等;
  2. Tokenizer:将原始文本进行分词,例:天气预报–>天气,预报;
  3. Token Filters:分词后的关键字进行加工,例:转小写、删除语气词、近义词和同义词等

Elasticsearch自带的分词器:

分词器(Analyzer) 特点
Standard(es默认) 支持多语言,按词切分并做小写处理
Simple 按照非字母切分,小写处理
Whitespace 按照空格来切分
Stop 去除语气助词,如the、an、的、这等
Keyword 不分词
Pattern 正则分词,默认\w+,即非字词符号做分割符
Language 常见语言的分词器(30+)

中文分词:

分词器名称 介绍 特点 地址
IK 实现中英文单词切分 自定义词库 https://github.com/medcl/elasticsearch-analysis-ik
Jieba python流行分词系统,支持分词和词性标注 支持繁体、自定义、并行分词 http://github.com/sing1ee/elasticsearch-jieba-plugin
Hanlp 由一系列模型于算法组成的java工具包 普及自然语言处理在生产环境中的应用 https://github.com/hankcs/HanLP
THULAC 清华大学中文词法分析工具包 具有中文分词和词性标注功能 https://github.com/microbun/elasticsearch-thulac-plugin

使用standard分词器

standard支持对英文的分词,并不支持中文分词。

使用IK分词器

安装:解压IK分词器安装包至elasticsearchplugins文件夹中,并重命名文件夹为analysis-ik

IK提供了两个分词算法ik_smartik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分。

五、Elasticsearch搜索原理


[Term、Posting List]
Elasticsearch使用倒排索引提升了查询效率。Elasticsearch分别为每个field都建立了一个倒排索引,KateJohn24Female这些叫term,而[1,2]就是Posting ListPosting List就是一个int的数组,存储了所有符合某个term的文档id

Posting List可以记录的数据:

  1. DocId:文档id,文档的原始信息
  2. TF:单词频率,记录该词再文档中出现的次数,用于后续相关性算分
  3. Position:位置,记录Field分词后,单词所在的位置,从0开始
  4. Offset:偏移量,记录单词在文档中开始和结束位置,用于高亮显示等

[Term Dictionary]
Elasticsearch为了能快速找到某个term,将所有的term排个序,二分法查找termlogN的查找效率,就像通过字典查找一样,这就是Term Dictionary

[Term Index]
B-Tree通过减少磁盘寻道次数来提高查询性能,Elasticsearch也是采用同样的思路,直接通过内存查找term,不读磁盘,但是如果term太多,Term Dictionary也会很大,放内存不现实,于是有了Term Index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解Term Index是一颗树:

这棵树不会包含所有的term,它包含的是term的一些前缀。通过Term Index可以快速地定位到Term Dictionary的某个offset,然后从这个位置再往后顺序查找。

所以Term Index不需要存下所有的term,而仅仅是他们的一些前缀与Term Dictionaryblock之间的映射关系,再结合FST(Finite State Transducers)的压缩技术,可以使Term Index缓存到内存中。从Term Index查到对应的Term Dictionaryblock位置之后,再去磁盘上找term,大大减少了磁盘随机读的次数。

[压缩]
Elasticsearch使用FST压缩Term Index外,Elasticsearch要求Posting List是有序的,对Posting List也有压缩技巧。 当Posting List至少有百万个文档id时, 此时对其压缩变得极其有意义。

[Frame Of Reference]

Step 1Delta-encode —— 增量编码
只记录元素与元素之间的增量,于是Posting List由[73,300,302,332,343,372]变为[73,227.2,30,11,29]

Step 2Split into blocks —— 分割成块
Lucene里每个块是256个文档ID,这样可以保证每个块,增量编码后,每个元素都不会超过256(1 byte

Step 3Bit packing —— 按需分配空间
对于第一个块,[73, 227, 2],最大元素是227,需要 8bit,只分配 8bit的空间;

但是对于第二个块,[30, 11, 29],最大的元素才30,只需要5 bit,只分配 5bit的空间。

[Roaring bitmaps]
Lucene有多个查询条件,需要快速求出多个Posting List的共同交集,通过使用Roaring bitmaps算法后两个Posting List做位运算即可求出交集。

假设有这样一个数组[3,6,7,10],我们使用bitmaps算法表示为[0,0,1,0,0,1,1,0,0,1]

Roaring bitmapsposting list按照65535为界限分块,第一块所包含的文档id范围在0~65535(2^16)之间,第二块的id范围是65536~131071,这样解决了Bitmap的缺点:存储空间随着文档个数线性增长。

Elasticsearch(二):进阶检索相关推荐

  1. 弹性搜索(elasticsearch)进阶--服务维护

    弹性搜索(elasticsearch)最新入门攻略 弹性搜索(elasticsearch)进阶–服务维护 系统配置 由于es再设计的时候就注重尽量减少调优项,基本不需要开发人员依据运行环境进行专门的调 ...

  2. Elasticsearch 4: 相关性检索和组合查询

    目录 1. 相关性评分 2. 相关度模型 2.1 布尔模型 2.2 向量空间模型 2.3 概率模型 2.4 语言模型 3. TF/IDF 4. BM25 4.1 词频饱和度 4.2 长度归一化 5. ...

  3. elasticsearch 的高级检索以及 Ik分词器的配置和使用

    首先准备测试数据 这是测试数据 点击去获取 使用上一篇我们安装的 kibana 将他们批量插入到es中 POST /bank/account/_bulk 数据插入成功之后可以在 psotman 调用 ...

  4. 用 mongodb + elasticsearch 实现中文检索

    2019独角兽企业重金招聘Python工程师标准>>> 而 elasticsearch 可以很好的支持各种语言的全文检索,但我们暂时又不想切换到 elasticsearch 作为后端 ...

  5. PopUpWindow使用详解(二)——进阶及答疑

    相关文章: 1.<PopUpWindow使用详解(一)--基本使用> 2.<PopUpWindow使用详解(二)--进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  6. 从二值检索到层次竞买图——让搜索广告关键词召回焕然新生

    丨目录: · 背景 · 广告改写的历史与新目标 · 从两阶段到一段式:二值海选 · 从一段式到联合召回:层次竞买图 · 关键词召回的业务思考 本文主要分享过去一年我们在搜索广告召回的传统领域--关键词 ...

  7. java es scroll,Elasticsearch Scroll分页检索案例分享

    Elasticsearch Scroll分页检索案例分享 1.准备工作 2.定义scroll检索dsl 首先定义一个简单的scroll dsl检索脚本 { ## 这里都是用常量在操作,实际场景中可以参 ...

  8. 《算法零基础100讲》(第20讲) 进制转换(二) - 进阶[C语言题解]

    文章目录 一. 知识普及 1.1 atoi 1.2 log 1.3 pow 1.4 floor 二. 进阶题解 168. Excel表列名称 171. Excel 表列序号 483. 最小好进制 一. ...

  9. Elasticsearch(二)

    Elasticsearch(二) 一. analysis与analyzer ​ analysis,文本分析是将全文本转换为一系列单词的过程,也叫分词.analysis是通过analyzer(分词器)来 ...

  10. [解题报告](第20讲) 进制转换(二) - 进阶

    零.写在前面 这是打卡的第二十天,今天题目还是有点难度的,不过就是题量下来了,可以沉淀一下之前的题目了,主要知识点在<算法零基础100讲>(第20讲) 进制转换(二) - 进阶https: ...

最新文章

  1. 区块链智能合约solidity入门
  2. DOS系统里,分屏显示目录的命令是什么??
  3. 自己喜欢的shell终端配置
  4. 前端学习(3022):vue+element今日头条管理-首页layont布局
  5. 剑指offer:12-17记录
  6. 面试问题汇总 精选 分析 解答 职业规划 part 2
  7. 网络数据采集技术—Java网络爬虫入门与实战 书稿纠错
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的共享单车管理系统
  9. java servlet jsp 实例_Servlet+JSP例子
  10. 论文阅读:A Progressive Architecture With Knowledge Review Network for Salient Object Detection
  11. [转载] python跨行 print:多用(),换行符\要小心,少用+或者不用(其它程序代码跨行用\就行,不能用括号)
  12. php数据入库流程,php数据库操作
  13. 软件项目详细设计方案怎么写?
  14. ad建集成库_AD16创建集成库的步骤
  15. CPU压力测试工具cpuburn
  16. 分享一下最近合成游戏源码
  17. oracle biee资料库,Hello oracle BIEE 资料
  18. c语言中 结构体对象,C语言中结构体详解
  19. 【2019.05】腾讯防水墙滑动验证码破解 python + selenium + OpenCV
  20. System.setOut(ps)重定义了输出流后,如何重定向控制台输出

热门文章

  1. MISFIT SHINE2评测相比一代的SHINE更加实用:也许是目前最好的智能手环
  2. php用户注册登录6,【php】ThinkPHP6通过Ucenter实现注册登录
  3. 1. 数理统计---数理统计基本概念
  4. 基于 RSSHub 搭建 RSS 生成器(群晖 Docker)
  5. 怎么配置内网IP SSL证书?
  6. 用excel函数COUNTIF实现两列数据对比找出不同数据
  7. 生物信息学在线服务器,48个实用的生信在线工具强烈推荐,不看是你的损失!...
  8. 一边裁员、一边招聘,领导到底想干啥?
  9. 马云回应豪宅谣言;淘宝上线了三架波音747进行拍卖;迪拜投1.4亿美元建模拟火星丨价值早报
  10. ES6最详细/易懂教程