vs网站开发 怎么运行,网站建设费用的会计核算,wordpress怎样在列表页使用瀑布流,移动商城积分兑换商城官网Elasticsearch#xff08;三#xff09;——Es搜索#xff08;简单使用、全文查询、复合查询#xff09;、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合
一、Es搜索
这里的 Es 数据博主自己上网找的#xff0c;为了练习 Es 搜索。
1、Elasticsearch 搜索入门
…Elasticsearch三——Es搜索简单使用、全文查询、复合查询、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合
一、Es搜索
这里的 Es 数据博主自己上网找的为了练习 Es 搜索。
1、Elasticsearch 搜索入门
搜索分为两个过程
当向索引中保存文档时默认情况下es 会保存两份内容一份是 _source 中的数据另一份则是通过分词、排序等一系列过程生成的倒排索引文件倒排索引中保存了词项和文档之间的对应关系。搜索时当 es 接收到用户的搜索请求之后就会去倒排索引中查询通过的倒排索引中维护的倒排记录表找到关键词对应的文档集合然后对文档进行评分、排序、高亮等处理处理完成后返回文档。
2、简单搜索
a、match_all——查询所有 简写
结果 因为没有设置查询条件所有最大的得分是 1.0。
这里并没有把所有的数据都展示出来因为默认是有分页功能的。
b、词项查询
即 term 查询就是根据词去查询查询指定字段中包含给定单词的文档term 查询不被解析只有搜索的词和文档中的词精确匹配才会返回文档。应用场景如人名、地名等等。
查询包含化学的
结果 这里是按照查询出来的分数从高到低排序。最上面是得分最高的也就是匹配度最高的。
c、分页
默认返回前 10 条数据es 中也可以像关系型数据库一样给一个分页参数
from从第几条开始。 size多少条数据。
d、过滤返回字段
如果返回的字段比较多又不需要这么多字段此时可以指定返回的字段 这里指定返回 name 字段
效果
e、最小评分
有的文档得分特别低说明这个文档和我们查询的关键字相关度很低。我们可以设置一个最低分只有得分超过最低分的文档才会被返回。
最低分要高于 1.78 结果
f、高亮
查询关键字高亮
3、Es 全文查询
a、match query
match query 会对查询语句进行分词分词后如果查询语句中的任何一个词项被匹配则文档就会被索引到。
前面都是输入词进行查询这里可以输入一句话来查询了
效果 这里是传一句话进去只要能有一个词能匹配这条记录就算是相关记录会返回来。
如果想要两个词都包含那么可以使用 operator 的 and 默认是 or
b、match_phrase query
match_phrase query 也会对查询的关键字进行分词但是它分词后有两个特点
分词后的词项顺序必须和文档中词项的顺序一致所有的词都必须出现在文档中
示例如下
结果 结果是什么都没有搜到。
因为这两个词分词之后是挨着的。但现在想要查询十一五和计算机这两个词不要挨在一起中间可以隔着其他东西。所以这里可以通过 slop 配置中间可以隔多少字符 效果
query 是查询的关键字会被分词器进行分解分解之后去倒排索引中进行匹配。
slop 是指关键字之间的最小距离但是注意不是关键之间间隔的字数。文档中的字段被分词器解析之后解析出来的词项都包含一个 position 字段表示词项的位置查询短语分词之后 的 position 之间的间隔要满足 slop 的要求。
c、match_phrase_prefix query效率低了解即可
这个类似于 match_phrase query只不过这里多了一个通配符match_phrase_prefix 支持最后一个词项的前缀匹配但是由于这种匹配方式效率较低因此大家作为了解即可。 这个查询过程会自动进行单词匹配会自动查找以计开始的单词默认是 50 个可以自己控制 match_phrase_prefix 是针对分片级别的查询假设 max_expansions 为 1可能返回多个文档但是只有一个词这是我们预期的结果。有的时候实际返回结果和我们预期结果并不一致原因在于这个查询是分片级别的不同的分片确实只返回了一个词但是结果可能来自不同的分片所以最终会看到多个词。
d、multi_match query
match 查询的升级版可以指定多个查询域意思就是查询多个字段
效果 这种查询方式还可以指定字段的权重
意思就是更在意 name 中是否有 java 加到其他字段也就是更在意哪些字段有 java。
结果
e、query_string query
query_string 是一种紧密结合 Lucene 的查询方式在一个查询语句中可以用到 Lucene 的一些查询语法
f、simple_query_string
这个是 query_string 的升级可以直接使用 、|、- 代替 AND、OR、NOT 等。
g、term query
词项查询。词项查询不会分析查询字符直接拿查询字符去倒排索引中比对。
h、terms query
词项查询但是可以给多个关键词。
i、range query
范围查询可以按照日期范围、数字范围等查询。
range query 中的参数主要有四个
gtltgtelte
查询价格大于等于 10小于等于 20 的书
效果 因为都在价格范围内没有说谁分高分低。
根据价格排序
效果
j、exists query
exists query 会返回指定字段中至少有一个非空值的文档 注意空字符串也是有值。null 是空值。
k、prefix query
前缀查询效率略低除非必要一般不太建议使用。
给定关键词的前缀去查询
l、wildcard query
wildcard query 即通配符查询。支持单字符和多字符通配符 表示一个任意字符。* 表示零个或者多个字符。
查询所有姓张的作者的书
查询所有姓张并且名字只有两个字的作者的书
m、regexp query
支持正则表达式查询。
查询所有姓张并且名字只有两个字的作者的书
n、 fuzzy query
在实际搜索中有时我们可能会打错字从而导致搜索不到在 match query 中可以通过 fuzziness属性实现模糊查询。
fuzzy query 返回与搜索关键字相似的文档。怎么样就算相似以LevenShtein 编辑距离为准。编辑距离是指将一个字符变为另一个字符所需要更改字符的次数更改主要包括四种
更改字符 javb–〉java 删除字符 javva–〉java 插入字符 jaa–〉java 转置字符 ajva–〉java
为了找到相似的词模糊查询会在指定的编辑距离中创建搜索关键词的所有可能变化或者扩展的集合然后进行搜索匹配
o、 ids query
根据指定的 id 查询
4、Es 复合查询
a、constant_score query
当我们不关心检索词项的频率TF对搜索结果排序的影响时可以使用 constant_score 将查询语句或者过滤语句包裹起来。
比如java 出现 10 词跟出现 1 词是一样的那么就可以这么做
b、bool query
bool query 可以将任意多个简单查询组装在一起有四个关键字可供选择四个关键字所描述的条件可以有一个或者多个。
must文档必须匹配 must 选项下的查询条件。should文档可以匹配 should 下的查询条件也可以不匹配。must_not文档必须不满足 must_not 选项下的查询条件。filter类似于 must但是 filter 不评分只是过滤数据。
例如查询 name 属性中必须包含 java同时书价不在 [0,35] 区间内info 属性可以包含 程序设计 也可以不包含程序设计 效果 这里还涉及到一个关键字 minmum_should_match 参数。
minmum_should_match 参数在 es 官网上称作最小匹配度。在之前学习的 multi_match 或者这里的should 查询中都可以设置 minmum_should_match 参数。
假设我们要做一次查询查询 name 中包含 语言程序设计 关键字的文档 在这个查询过程中首先会进行分词分词结果如下 分词后的 term 会构造成一个 should 的 bool query每一个 term 都会变成一个 term query 的子句。换句话说上面的查询和下面的查询等价。
在这两个查询语句中都是文档只需要包含词项中的任意一项即可文档就回被返回在 match 查询中可以通过 operator 参数设置文档必须匹配所有词项。
如果想匹配一部分词项就涉及到一个参数就是 minmum_should_match 即最小匹配度。即至少匹配多少个词。 50% 表示词项个数的 50%。就是说至少有一般的词量被匹配才会返回。
如下两个查询等价参数 4 是因为查询关键字分词后有 4 项 调整数字数字越多意味着要匹配的词汇越多结果越少。
c、dis_max query
假设现在有两本书 肉眼观察第二个的 comtent 语句有两个关键字第一个只是 title 和 content 各有一个关键字感觉第二个和查询关键字相似度更高。但是实际查询结果并非这样。
要理解这个原因我们需要来看下 should query 中的评分策略
首先会执行 should 中的两个查询。对两个查询结果的评分求和。对求和结果乘以匹配语句总数。在对第三步的结果除以所有语句总数。
反映到具体的查询中
前者
title 中 包含 java假设评分是 1.1content 中包含解决方案假设评分是 1.2有得分的 query 数量这里是 2总的 query 数量也是 2
最终结果 1.11.2*2/22.3
后者
title 中 不包含查询关键字没有得分content 中包含解决方案和 java假设评分是 2有得分的 query 数量这里是 1总的 query 数量也是 2
最终结果 2*1/21
在这种查询中title 和 content 相当于是相互竞争的关系所以我们需要找到一个最佳匹配字段。
为了解决这一问题就需要用到 dis_max querydisjunction max query分离最大化查询匹配的文档依然返回但是只将最佳匹配的评分作为查询的评分。这里就是跟 title 和 content 都去匹配谁的得分高就用谁不在给这两个去算综合的分数 查询结果如下 这一次的结果就符合心中的预期了。
在 dis_max query 中还有一个参数 tie_breaker 取值在01在 dis_max query 中是完全不考虑其他 query 的分数只是将最佳匹配的字段的评分返回。但是有的时候我们又不得不考虑一下其他 query 的分数此时可以通过 tie_breaker 来优化 dis_max query。 tie_breaker 会将其他 query 的分数乘以 tie_breaker 然后和分数最高的 query 进行一个综合计算
如果这里设置回 1结果又会变得跟原来一样。
d、function_score query
场景例如想要搜索附近的肯德基搜索的关键字是肯德基但是我希望能够将评分较高的肯德基优先展示出来。但是默认的评分策略是没有办法考虑到餐厅评分的他只是考虑相关性这个时候可以通过 function_score query 来实现。
准备两条测试数据 现在搜索标题中包含 java 关键字的文档
查询结果如下 默认情况下id 为 2 的记录得分较高因为他的 title 中包含两个 java。
如果我们在查询中希望能够充分考虑 votes 字段将 votes 较高的文档优先展示就可以通过function_score 来实现。
具体的思路就是在旧的得分基础上根据 votes 的数值进行综合运算重新得出一个新的评分。
具体有几种不同的计算方式
weightrandom_scorescript_scorefield_value_factor
1weight
weight 可以对评分设置权重就是在旧的评分基础上乘以 weight他其实无法解决我们上面所说的问题。具体用法如下
2random_score
random_score 会根据 uid 字段进行 hash 运算生成分数使用 random_score 时可以配置一个种子如果不配置默认使用当前时间。
3script_score
自定义评分脚本。假设每个文档的最终得分是旧的分数加上votes。查询方式如下 现在最终得分是 (oldScorevotes)*oldScore 。
如果不想乘以 oldScore查询方式如下 通过 boost_mode 参数可以设置最终的计算方式。该参数还有其他取值
multiply分数相乘sum分数相加avg求平均数max最大分min最小分replace不进行二次计算
4field_value_factor
这个的功能类似于 script_score 但是不用自己写脚本。 假设每个文档的最终得分是旧的分数乘以votes。查询方式如下 默认的得分就是 oldScore * votes 。 还可以利用 es 内置的函数进行一些更复杂的运算 此时最终的得分是sqrt(votes)。 modifier 中可以设置内置函数其他的内置函数还有 另外还有个参数 factor 影响因子。字段值先乘以影响因子然后再进行计算。以 sqrt 为例计算方式为 sqrt ( factor * votes) 还有一个参数 max_boost 控制计算结果的范围 max_boost 参数表示 functions 模块中最终的计算结果上限。如果超过上限就按照上线计算。
e、boosting query
boosting query 中包含三部分
positive得分不变negative降低得分negative_boost降低的权重 可以看到id 为 86 的文档满足条件因此它的最终得分在旧的分数上 *0.5 。
关系型数据库中有表的关联关系在 es 中我们也有类似的需求例如订单表和商品表在 es 中这样的一对多一般来说有两种方式
嵌套文档nested父子文档
f、嵌套文档
假设有一个电影文档每个电影都有演员信息 注意 actors 类型要是 nested。 这是因为 nested 文档在 es 内部其实也是独立的 lucene 文档只是在我们查询的时候es 内部帮我们做了 join 处理所以最终看起来就像一个独立文档一样。因此这种方案性能并不是特别好。
g、嵌套查询
这个用来查询嵌套文档
h、父子文档
相比于嵌套文档父子文档主要有如下优势
更新父文档时不会重新索引子文档创建、修改或者删除子文档时不会影响父文档或者其他的子文档。子文档可以作为搜索结果独立返回。
例如学生和班级的关系 s_c 表示父子文档关系的名字可以自定义。join 表示这是一个父子文档。relations 里边class 这个位置是 parentstudent 这个位置是 child。
接下来插入两个父文档 再来添加三个子文档 首先大家可以看到子文档都是独立的文档。特别需要注意的地方是子文档需要和父文档在同一个分片上所以 routing 关键字的值为父文档的 id。另外name 属性表明这是一个子文档。
父子文档需要注意的地方
每个索引只能定义一个 join filed父子文档需要在同一个分片上查询修改需要routing可以向一个已经存在的 join filed 上新增关系
i、 has_child query
通过子文档查询父文档使用 has_child query。 查询 wangwu 所属的班级。
j、has_parent query
通过父文档查询子文档 查询二班的学生。但是大家注意这种查询没有评分。
可以使用 parent id 查询子文档 通过 parent id 查询默认情况下使用相关性计算分数。
k、小结
整体上来说
普通子对象实现一对多会损失子文档的边界子对象之间的属性关系丢失。nested 可以解决第 1 点的问题但是 nested 有两个缺点更新主文档的时候要全部更新不支持子文档属于多个主文档。父子文档解决 1、2 点的问题但是它主要适用于写多读少的场景。
二、Es 地理位置查询
1、数据准备
创建一个索引
PUT geo
{
mappings: {
properties: {
name:{
type: keyword
},
location:{
type: geo_point
}
}
}
}准备一个 geo.json 文件
{index:{_index:geo,_id:1}}
{name:西安,location:34.288991865037524,108.9404296875}
{index:{_index:geo,_id:2}}
{name:北京,location:39.926588421909436,116.43310546875}
{index:{_index:geo,_id:3}}
{name:上海,location:31.240985378021307,121.53076171875}
{index:{_index:geo,_id:4}}
{name:天津,location:39.13006024213511,117.20214843749999}
{index:{_index:geo,_id:5}}
{name:杭州,location:30.259067203213018,120.21240234375001}
{index:{_index:geo,_id:6}}
{name:武汉,location:30.581179257386985,114.3017578125}
{index:{_index:geo,_id:7}}
{name:合肥,location:31.840232667909365,117.20214843749999}
{index:{_index:geo,_id:8}}
{name:重庆,location:29.592565403314087,106.5673828125}最后执行如下命令批量导入 geo.json 数据
curl -XPOST http://localhost:9200/geo/_bulk?pretty -H content-type:application/json --data-binary geo.json可能用到的工具网站主要用来验证搜索的结果对不对 http://geojson.io/#map6/32.741/116.521
2、geo_distance query
给出一个中心点查询距离该中心点指定范围内的文档
以(34.288991865037524,108.9404296875) 为圆心以 600KM 为半径这个范围内的数据。 效果
3、geo_bounding_box query
在某一个矩形内的点通过两个点锁定一个矩形 以南京经纬度作为矩形的左上角以舟山经纬度作为矩形的右下角构造出来的矩形中包含上海和杭州两个城市。
4、geo_polygon query
在某一个多边形范围内的查询。 给定多个点由多个点组成的多边形中的数据。
上图是三个点也就是三角形。
5、geo_shape query
geo_shape 用来查询图形针对 geo_shape 两个图形之间的关系有相交、包含、不相交。
新建索引 然后添加一条线 接下来查询某一个图形中是否包含该线 relation 属性表示两个图形的关系
within包含intersects相交disjoint不相交
三、Es 特殊查询
1、more_like_this query
more_like_this query 可以实现基于内容的推荐给定一篇文章可以查询出和该文章相似的内容。
fields要匹配的字段可以有多个。like要匹配的文本。min_term_freq词项的最低频率默认是 2。特别注意这个是指词项在要匹配的文本中的频率而不是 es 文档中的频率。max_query_termsquery 中包含的最大词项数目。min_doc_freq最小的文档频率搜索的词至少在多少个文档中出现少于指定数目该词会被忽略。max_doc_freq最大文档频率。analyzer分词器默认使用字段的分词器。stop_words停用词列表。minmum_should_match
2、script query——脚本查询用的少 3、 percolate query用的少 4、搜索高亮
普通高亮默认会自动添加 em 标签
5、排序
排序很简单默认是按照查询文档的相关度来排序的即 _score 字段
四、聚合操作
1、Max Aggregation——统计最大值 也可以通过脚本来查询最大值
2、 Min / Avg / Sum Aggregation——统计最小值、平均值、求和
Min Aggregation统计最小值用法和 Max Aggregation 基本一致。
Avg Aggregation统计平均值用法和 Max Aggregation 基本一致。
Sum Aggregation求和用法和 Max Aggregation 基本一致。
3、Cardinality Aggregation——基数统计
cardinality aggregation 用于基数统计。类似于 SQL 中的 distinct count(0)
text 类型是分析型类型默认是不允许进行聚合操作的如果相对 text 类型进行聚合操作需要设置其 fielddata 属性为 true这种方式虽然可以使 text 类型进行聚合操作但是无法满足精准聚合如果需要精准聚合可以设置字段的子域为 keyword。
a、方式一不推荐
重新定义 books 索引 定义完成后重新插入数据。
接下来就可以查询出版社的总数量 这种聚合方式可能会不准确。可以将 publish 设置为 keyword 类型或者设置子域为 keyword。
b、方式二
上面那种聚合方式可能会不准确。可以将 publish 设置为 keyword 类型或者设置子域为 keyword 查询结果如下
4、Stats Aggregation——基本统计
基本统计一次性返回 count、max、min、avg、sum
5、Extends Stats Aggregation——高级统计
高级统计比 stats 多出来平方和、方差、标准差、平均值加减两个标准差的区间
6、Percentiles Aggregation——百分位统计
百分位统计 效果 这个百分位统计意思就是在书的总数量的百分之一的时候这个书是多少钱总数量的百分之五的时候又是多少钱以此类推。
7、Value Count Aggregatio——按照字段统计文档数量
可以按照字段统计文档数量包含指定字段的文档数量
五、桶聚合bucket
桶聚合有点像 mysql 的分组查询。
1、Terms Aggregation——分组聚合
Terms Aggregation 用于分组聚合例如统计各个出版社出版的图书总数量
统计结果如下 在 terms 分桶的基础上还可以对每个桶进行指标聚合。
统计不同出版社所出版的图书的平均价格 统计结果如下
2、 Filter Aggregation——过滤器聚合
过滤器聚合。可以将符合过滤器中条件的文档分到一个桶中然后可以求其平均值。
例如查询书名中包含 java 的图书的平均价格
3、Filters Aggregation——多过滤器聚合
多过滤器聚合。过滤条件可以有多个。
例如查询书名中包含 java 或者 office 的图书的平均价格
4、Range Aggregation——范围聚合
按照范围聚合在某一个范围内的文档数统计。
例如统计图书价格在 0-50、50-100、100-150、150以上的图书数量
5、 Date Range Aggregation——统计日期
Range Aggregation 也可以用来统计日期但是也可以使用 Date Range Aggregation后者的优势在于可以使用日期表达式。
6、Date Histogram Aggregation——时间直方图聚合
时间直方图聚合。
例如统计各个月份的博客数量
7、 Missing Aggregation——空值聚合
空值聚合。
统计所有没有 price 字段的文档 8、Children Aggregation——根据父子关系分桶
可以根据父子文档关系进行分桶。
查询子类型为 student 的文档数量
9、Geo Distance Aggregation 10、IP Range Aggregation 六、管道聚合
管道聚合相当于在之前聚合的基础上再次聚合。
1、Avg Bucket Aggregation 2、Max Bucket Aggregation
统计每个出版社所出版图书的平均值然后再统计平均值中的最大值
3、Min Bucket Aggregation
统计每个出版社所出版图书的平均值然后再统计平均值中的最小值。
4、Sum Bucket Aggregation
统计每个出版社所出版图书的平均值然后再统计平均值之和
5、Stats Bucket Aggregation 6、Extended Stats Bucket Aggregation 7、Percentiles Bucket Aggregation