一、载入数据

1.1 新建和删除索引

在ElasticSearch中,索引的含义和关系型数据库中的数据库类似。如下命令可以查看当前节点下所有索引:

curl -X GET 'http://localhost:9200/_cat/indices?v'

新建Index可以直接向Elastic服务器发出PUT请求。如下建立mysql_log索引:

curl -X PUT 'localhost:9200/mysql_log'

删除索引使用DELETE请求,如下:

curl -X DELETE 'localhost:9200/mysql_log'

载入数据

在ElasticSearch中

curl -X PUT "localhost:9200/mysql_log/test/1?pretty" -H 'Content-Type: application/json' -d'
{"time" : "2020/12/30 11:30:24","sql_type" : "select","sql" : "select col1 from tab1 where col2 = 3;"
}
'
curl -X PUT "localhost:9200/mysql_log/test/2?pretty" -H 'Content-Type: application/json' -d'
{"time" : "2020/12/30 11:30:24","sql_type" : "insert","sql" : "insert into tab1 values (1, 1, 1);"
}
'
curl -X PUT "localhost:9200/mysql_log/test/3?pretty" -H 'Content-Type: application/json' -d'
{"time" : "2020/12/30 11:31:15","sql_type" : "update","sql" : "update tab1 set col1 = 4 WHERE col3 = 4;"
}
'
curl -X PUT "localhost:9200/mysql_log/test/4?pretty" -H 'Content-Type: application/json' -d'
{"time" : "2020/12/30 11:30:24","sql_type" : "delete","sql" : "delete from tab1 WHERE col1 = 4;"
}
'

如果成功,则会返回如下结果:

{"_index" : "mysql_log","_type" : "test","_id" : "3","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 3,"_primary_term" : 1
}

这里,每一条数据都被称作一个文档,由_index_type_id唯一标识一个文档。

短语匹配

match和match_phrase比较

在上节中我们载入了四个文档,其中文档中sql字段的值如下:

select col1 from tab1 where col2 = 3;
insert into tab1 values (1, 1, 1);
update tab1 set col1 = 4 WHERE col3 = 4;
delete from tab1 WHERE col1 = 4;

如果我们使用match进行搜索时:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match": {"sql": "col1 from"}}
}
'

会返回三条结果,篇幅原因只显示部分结果

"_score" : 1.1149836,
"sql" : "delete from tab1 WHERE col1 = 4;""_score" : 1.0498221,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 0.33698124,
"sql" : "update tab1 set col1 = 4 WHERE col3 = 4;"

其中,_score是针对匹配程度进行的一个打分,match是使用TF/IDF的标准来对匹配程度进行打分。其中TF/IDF就是将词频term frequency,即col1from在相关文档的sql字段中出现的频率)和反向文档频率inverse document frequency,即col1from在所有文档的sql字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。
上面的例子中,第一条比第二条字段长度要短,所以第一条的_score要大些。第三条由于只匹配了col1,所以_score较小。
接下来使用match_phrase进行查询:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match_phrase": {"sql": "col1 from"}}
}
'

只会返回一条结果:

"_score" : 1.0498221,
"sql" : "select col1 from tab1 where col2 = 3;"

因为match_phrase查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含全部搜索词项,且位置与搜索词项相同的文档。相比较与match查询,match_phrase更为严格。

词项的位置

当一个字符串被分析器分析后,不但会分析为一个词项列表,还会记录词项的位置信息。例如对于col1 from进行分析:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{"analyzer": "standard","text": "col1 from"
}'

会返回如下结果:

{"tokens": [{"token": "col1","start_offset": 0,"end_offset": 4,"type": "<ALPHANUM>","position": 0}, {"token": "from","start_offset": 5,"end_offset": 9,"type": "<ALPHANUM>","position": 1}]
}

所以match_phrase会根据词项的位置,利用倒排索引,来实现对词项信息敏感的查询

短语

本节中的match_phrase查询就是针对短语进行匹配,短语匹配就是词项及词项位置都相同的才能匹配。

混合起来

由于短语匹配的要求过于严格。例如上面例子中的delete from tab1 WHERE col1 = 4;虽然包含词项col1from,只是词项的位置没有达到要求,使用短语匹配的话就会失败。此时需要将slop参数将灵活度引入短语匹配中:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match_phrase": {"sql": {"query": "col1 from","slop":  1}}}
}
'

当slop为1时,只能返回一条结果"sql" : "select col1 from tab1 where col2 = 3;";但是当slop为4的时候,就会返回包含delete from tab1 WHERE col1 = 4;的两条结果了。这是因为在delete from tab1 WHERE col1 = 4;from相较于col1偏移了4个位置,所以设置slop为4的话,就会匹配到两条结果。
如果slop设置的足够大,那么match_phrase会匹配到所有包含词项col1from的文档。由此可见slop参数可以扩大match_phrase搜索范围。

多值字段

如果文档中的字段是一个数组类型,例如:

curl -X PUT "localhost:9200/test2/groups/1?pretty" -H 'Content-Type: application/json' -d'
{"names": [ "John Abraham", "Lincoln Smith"]
}
'

然后使用match_phrase查询

curl -X GET "localhost:9200/test2/groups/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match_phrase": {"names": "Abraham Lincoln"}}
}
'

由于Abraham的位置是2,Lincoln位置是3。在以前版本中,是可以匹配到这条文档的。但是在ElasticSearch 7.10.1版本中发生了改变,是匹配不到这条文档。

越近越好

带有参数slopmatch_phrase会将查询词条的邻近度考虑到最终相关度_score中。如下所示:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match_phrase": {"sql": {"query": "col1 from","slop":  4}}}
}
'

返回结果为:

"_score" : 1.0498221,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 0.36330914,
"sql" : "delete from tab1 WHERE col1 = 4;"

可以看出col1from近的_score较高,反之较小。

使用临近度提高相关性

由于近似查询需要所有的词项都出现在文档中才可以匹配,要求过于严格。因此,我们可以设计一个可以匹配部分的词项,并且利用近似查询来对结果进行评分。我们可以使用bool查询来将多个查询分数累计起来。查询如下:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"bool": {"must": {"match": { "sql": {"query":                "col1 from tab1","minimum_should_match": "30%"}}},"should": {"match_phrase": { "sql": {"query": "col1 from tab1","slop":  50}}}}}
}
'

在这条bool查询中,将must中的match查询分数和should中的match_phrase查询分数合并得到最终的_score。其中must子句的查询规则是结果必须要包含在结果集的,minimum_should_match就是最小匹配度;should子句的查询可以添加一些查询规则来增加匹配结果的_score。上面查询的结果如下:

"_score" : 2.3103652,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 1.6266546,
"sql" : "delete from tab1 WHERE col1 = 4;""_score" : 0.4365243,
"sql" : "update tab1 set col1 = 4 WHERE col3 = 4;""_score" : 0.10536051,
"sql" : "insert into tab1 values (1, 1, 1);"

由上面的结果可以看出虽然match_phrase是对于col1 from tab1进行查询,但是并不会影响update tab1 set col1 = 4 WHERE col3 = 4;insert into tab1 values (1, 1, 1);结果的显示,尽管词项没有完全匹配。如果我们将最小匹配度minimum_should_match的参数调到70%,那么就只会匹配到三条结果,insert into tab1 values (1, 1, 1);会因为匹配度过低而过滤掉:

"_score" : 2.3103652,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 1.6266546,
"sql" : "delete from tab1 WHERE col1 = 4;""_score" : 0.4365243,
"sql" : "update tab1 set col1 = 4 WHERE col3 = 4;"

性能优化

match_phrase查询效率要比match查询低得多,因为match_phrase查询必须计算并比较多个可能重复词项的位置。我们可以通过减少需要通过短语查询的文档总数来提高match_phrase查询的效率。
主要思路如下:
match查询先过滤出需要的数据,然后再用match_phrase来根据词项距离提高doc分数,同时match_phrase只针对每个分片的分数排名前N个文档起作用,来重新调整他们的分数,这个过程称之为rescoring(重打分)。
查询如下:

curl -X GET "localhost:9200/mysql_log/test/_search?pretty" -H 'Content-Type: application/json' -d'
{"query": {"match": {  "sql": {"query":                "col1 from tab1","minimum_should_match": "30%"}}},"rescore": {"window_size": 4, "query": {         "rescore_query": {"match_phrase": {"sql": {"query": "col1 from tab1","slop":  50}}}}}
}
'

数据还是使用的最初的数据,该索引中只有4条文档,并且都在同一个分片中。window_size是每一分片进行重新评分的顶部文档数量,这个例子中设置为4的话就可以覆盖所有match搜索到的文档结果。结果如下:

"_score" : 2.3103652,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 1.6266546,
"sql" : "delete from tab1 WHERE col1 = 4;""_score" : 0.4365243,
"sql" : "update tab1 set col1 = 4 WHERE col3 = 4;""_score" : 0.10536051,
"sql" : "insert into tab1 values (1, 1, 1);"

当我们将window_size设置为1后,结果如下:

"_score" : 1.6266546,
"sql" : "delete from tab1 WHERE col1 = 4;""_score" : 1.1551826,
"sql" : "select col1 from tab1 where col2 = 3;""_score" : 0.4365243,
"sql" : "update tab1 set col1 = 4 WHERE col3 = 4;""_score" : 0.10536051,
"sql" : "insert into tab1 values (1, 1, 1);"

可以看出只对delete from tab1 WHERE col1 = 4;进行了重打分,因为在match查询时delete from tab1 WHERE col1 = 4;_score是最高的,由于window_size设置为1,所以只对delete from tab1 WHERE col1 = 4;重打分了。

ElasticSearch近似匹配调研相关推荐

  1. ElasticSearch 的使用-整体方向和调研笔记

    目录 ElasticSearch 的使用-整体方向和调研笔记 介绍 ElasticSearch 安装 启动 创建索引 插件管理 使用 Kibana 下载 启动 汉化 实际运用的思考 ElasticSe ...

  2. 让Elasticsearch飞起来!百亿级实时查询优化实战

    最近的一个项目是风控过程数据实时统计分析和聚合的一个 OLAP 分析监控平台,日流量峰值在 10 到 12 亿上下,每年数据约 4000 亿条,占用空间大概 200T. 面对这样一个数据量级的需求,我 ...

  3. 百亿级实时查询优化实战,让你的Elasticsearch飞起来

    最近的一个项目是风控过程数据实时统计分析和聚合的一个 OLAP 分析监控平台,日流量峰值在 10 到 12 亿上下,每年数据约 4000 亿条,占用空间大概 200T. 面对这样一个数据量级的需求,我 ...

  4. 《从Lucene到Elasticsearch:全文检索实战》已出版!

    #一.前言 决定在CSDN写博客的原因是想把自己解决过的问题.踩过的坑.总结出来的经验记录下来,作为编程之路的"笔记本",同时也能给遇到同样问题的人提供参考.节省时间,写书的初衷也 ...

  5. ElasticSearch教程——proximity match 近似匹配

    ElasticSearch汇总请查看:ElasticSearch教程--汇总篇 1.什么是近似匹配 两个句子 java is my favourite programming language, an ...

  6. Elasticsearch 之(20)proximity match 近似匹配

    1.什么是近似匹配 两个句子 java is my favourite programming language, and I also think spark is a very good big ...

  7. 行业elasticsearch容器化存储分离调研报告

    一.行业es容器化&存储分离架构行业调研 1.1 行业es容器化调研概述 目前通过联系各个公司的同学&前同事.结合网上公开资料&官方云服务使用文档,共统计10家公司,基本覆盖头 ...

  8. elasticsearch 深入 —— 近似匹配

    近似匹配 使用 TF/IDF 的标准全文检索将文档或者文档中的字段作一大袋的词语处理. match 查询可以告知我们这大袋子中是否包含查询的词条,但却无法告知词语之间的关系. 思考下面这几个句子的不同 ...

  9. ElasticSearch 同城容灾调研

    基础知识: 服务节点角色:master node,data node,client node 主节点负责集群状态管理,创建或者删除索引,分配分片等操作,选主需满足quorum原则 数据节点负责存储数据 ...

  10. 腾讯Elasticsearch海量规模背后的内核优化剖析

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:黄华,腾讯 TEG 云架构平台部研发工程师 背景 Elast ...

最新文章

  1. 计算机应用试卷分析讲评课教案,数学试卷讲评课教案.doc
  2. nuke linux 插件,Nuke 插件:镜头光晕 Optical Flares v1.0.86(含预设)Win/Mac/Linux
  3. Django的静态文件的配置
  4. 论论资排辈和有能者居之
  5. Android Animation动画效果简介
  6. C++对象内存布局--④VS编译器--单个虚拟继承
  7. Golang Web入门(4):如何设计API
  8. 博弈树α-β剪枝搜索学习参考资料
  9. android 触摸屏 不支持 配置,Android触摸屏配置调试
  10. Dataframe 新增一列, apply 通用方法
  11. 手把手教你搭建pytorch深度学习网络
  12. css3实现loading动画效果
  13. TLB cache 原理
  14. C/C++[codeup 1785]字符串连接
  15. Linux邮件服务器怎么用?
  16. 简明python教程最新pdf_《简明Python教程》PDF高清 初学者的极佳教材 限时免费领取...
  17. 神舟电脑怎么重装系统 神舟电脑重装系统步骤
  18. iDrac6 虚拟控制台 连接失败
  19. 怎么给HTML文件加背景,设置文件夹背景,如何设置文件夹背景颜色
  20. mahout类似的开源项目

热门文章

  1. Linux操作系统中df和du命令常见用法
  2. Python学习之路_day_08(函数介绍)
  3. 【Java TCP/IP Socket】UDP Socket(含代码)
  4. Android RxJava
  5. 垃圾回收机制,是不是这样理解?
  6. 利用GDI+ for.NET 给图片加水印标记
  7. 【推荐】会被快速否决的9种求职者.
  8. ModuleNotFoundError: No module named ‘pyemd‘ 解决
  9. 648 页全彩 + 395张插图 的机器翻译传奇巨作 -- 送几本~
  10. 无需多个模型也能实现知识整合?港中文MMLab提出“烘焙”算法,全面提升ImageNet性能...