Elasticsearch 是一个开源的搜索引擎,Elasticsearch 使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。
已经在其他文档中详细介绍,此次仅做简单步骤介绍
查询表达式( Query DSL )是一种非常灵活又富有表现力的查询语言, Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分
上述查询会搜索ES中的所有索引,但通常只需要去固定一个或几个索引中搜索,搜索全部无疑会造成资源的浪费,在ES中可以通过以下几种方法来指定索引
以上表示在 mysql-shop_trades-order_statics 索引下查找数据
这里也可以用逗号分割多个匹配索引
ES本身没有group关键词搜索,但支持聚合查询,,需要使用关键字aggs
order by:注意日期格式和数值格式才支持排序;文本不支持,如果要排序, 需把字段设置为not analysis
select distinct(id) from table
match_phrase :查询分析文本,创建词组查询
>
term 查询是简单查询,接受一个字段名和参数,进行精准查询,类似sql中:
ES中对应的DSL如下:
在ES5x及以上版本,字符串类型需设置为keyword或text类型,根据类型来进行精确值匹配。
当进行精确值查询,可以使用过滤器,因为过滤器的执行非常快,不会计算相关度(ES会计算查询评分),且过滤器查询结果容易被缓存。
bool过滤器组成部分:
当我们需要多个过滤器时,只须将它们置入 bool 过滤器的不同部分即可。
terms是包含的意思,如下:
name包含["奥尼尔","麦迪"]
返回结果:
range查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:
类似sql中的范围查询:
ES中对应的DSL如下:
如下sql,age不为null:
ES中对应的DSL如下:
如下sql,age为null:
ES中对应的DSL如下:
注:missing查询在5x版本已经不存在。
匹配包含 not analyzed(未分词分析)的前缀字符:
匹配具有匹配通配符表达式( (not analyzed )的字段的文档。 支持的通配符:
1) 它匹配任何字符序列(包括空字符序列);
2) 它匹配任何单个字符。
请注意,此查询可能很慢,因为它需要遍历多个术语。
为了防止非常慢的通配符查询,通配符不能以任何一个通配符或 开头。
正则表达式查询允许您使用正则表达式术语查询。
举例如下:
注意: 的匹配会非常慢,你需要使用一个长的前缀,
通常类似+通配符查询的正则检索性能会非常低。
模糊查询查找在模糊度中指定的最大编辑距离内的所有可能的匹配项,然后检查术语字典,以找出在索引中实际存在待检索的关键词。
举例:
检索索引test_index中,type为user的全部信息。不过在 es6x 版本,一个index仅有一个type,未来 es7x 版本,将取消type,所以这个查询没啥意义。
返回指定id的全部信息。
全文检索查询,是通过分析器,对查询条件进行分析,然后在全文本字段进行全文查询。
全文搜索取决于mapping中设定的analyzer(分析器),这里使用的是ik分词器。
所以在进行查询开发时候,需要先了解index的mapping,从而选择查询方式。
匹配查询接受文本/数字/日期类型,分析它们,并构造查询。
对查询传入参数进行分词,搜索词语相同文档。
match_phrase查询分析文本,并从分析文本中创建短语查询。
用户已经渐渐习惯在输完查询内容之前,就能为他们展现搜索结果,这就是所谓的即时搜索(instant search) 或输入即搜索(search-as-you-type) 。
不仅用户能在更短的时间内得到搜索结果,我们也能引导用户搜索索引中真实存在的结果。
例如,如果用户输入 johnnie walker bl ,我们希望在它们完成输入搜索条件前就能得到: Johnnie Walker Black Label 和 Johnnie Walker Blue Label 。
match_phrase_prefix与match_phrase相同,除了它允许文本中最后一个术语的前缀匹配。
在ElasticSearch中创建索引时,可以为创建的索引指定索引的属性设定,映射关系,别名等 *** 作,然而,每次创建索引都要指定这些参数比较麻烦。ES提供了一种方法可以在索引创建时自动为索引进行设置,这种方法叫做索引模板。
上面这段是使用ES RestAPI创建索引模板:
index_patterns :用来指定适用于该模板的索引名称,一般可以使用前缀加 的方法来进行设定。可以设置多个。
order :可以同时指定多个模板,在存在冲突的情况下,order值高的可以覆盖order值低的模板。如果 order 值相同,则情况不可预测。
setting , mapping , aliases :与索引设定中的一致。
version :可以选择为索引模板添加版本号。
ES中存在多个模板匹配到同一个索引的情况。这时候,产生的索引会将两者的配置合并产生新的索引设置内容。如果存在内容冲突的情况,使用 order 值进行解决,详情见上一节的描述。
以下面为例:
创建一个新的索引:
结果可见, High 的类型被覆盖成了 text 类型。
如果将test_temp1的 order 值调成0会怎么样呢。笔者试了很多次, High 的值一直保持 integer 的类型。而文档中描述这种情况是不可预知的。
当一个事先未设置的字段被加入到一个索引中时,ES会怎样处理呢?索引提供了 dynamic 字段来提供不同的处理策略。 dynamic 字段有3个可选值, true , false 以及 strict
true : 这是 dynamic 字段的默认值,在这种情况,ES会接收字段并根据其类型进行自动映射。
false : 这个字段关闭了动态mapping的功能,如果文档中包含没有事先mapping的字段,这个字段会被存储,但是在搜索时是无法被搜索到的。我们可以通过修改mapping,然后使用 _update_by_query API,使得该字段可以被索引到。
strict : 严格mapping,如果有不符合映射关系的字段,索引 *** 作会失败。
上文提到,ES检测到字符串类型时会自动对其进行日期类型检测。这个行为可以在索引mapping中开启或关闭,默认是处于开启状态。可以通过将 date_detection 设置成 false 来将该功能关闭。
日期类型检测默认会匹配这样的日期格式: "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"
用户也可以在 dynamic_date_formats 中自定义日期格式。
有一些程序会在json格式中将数字类型设置成字符串,ES可以对其进行自动识别,但是该功能默认是关闭的,需要用户手动打开。
ES还提供了动态模板这种方法来对动态识别出来的字段进行处理。
动态模板的格式如下:
其中,模板的名称可以自定义, mapping 部分则是对动态识别出来的字段进行处理。两种之间则是用来定义进行mapping的条件。这部分可能用到 match_mapping_type , match , unmatch , match_pattern , path_match , path_unmatch 。
动态模板是按顺序进行匹配的,当一个类型命中了一个模板的条件后,就不会再进行后续匹配了。
在模板已经设置的情况下,如果使用put方法设置动态模板。新的模板会覆盖原有模板。
match_mapping_type 是指的ES的json解析器解析出来的类型,由于json类型不会告诉ES一个整形类型的长度是32位还是64位,也不会告诉ES一个浮点数是单精度还是双精度,因此ES总会使用适用范围更广的类型。
用来做字段名匹配的, match 用来指定需要匹配的字段模式,而 unmatch 则用来将 match 中包含的部分不需要做动态匹配的字段剔除。
以上这段会做以下动作:将未事先指定的字符串类型自动,如果其字段名前缀是 long_ ,且后缀为 _text ,将其映射为 long 类型。
match_pattern 可以用来指定match的匹配方式,可以指定其为 regex ,这样就会以java正则匹配的方式来对字段名进行匹配。如果不指定,默认会使用简单的 wildchart 方式进行匹配。
与 match 及 unmatch 类似,区别是 path_match 和 path_unmatch 匹配的的模式是xxxxxxxxx,这种模式用于object属性的映射匹配。
以上将一个人的first name和last name进行组合拼成了一个全名。
动态模板有两个内置属性 {name} 和 {dynamic_type} 用来指代字段名称及其自动识别出来的类型。
以上这段,将识别出来的字符串类型的分词器设置成与其属性名相同。并且关闭了除此之外所有属性的 doc_values 。
首先,你的表肯定是做了外键等约束的,所以删除,要从最外层删除。假设你的数据库是Sql Server的。
1、技能表
delete from 技能表 where 人物id in (select 人物id from 人物表 where 账号id in (select 账号id from 账号表 where datediff(day,上次登录时间lasttime,getdate())>=3))
2、装备属性表
delete from 装备属性表 where 装备id in (select 装备id from 装备表 where 人物id in (select 人物id from 人物表 where 账号id in (select 账号id from 账号表 where datediff(day,上次登录时间lasttime,getdate())>=3)))
3、装备表
delete from 装备表 where 人物id in (select 人物id from 人物表 where 账号id in (select 账号id from 账号表 where datediff(day,上次登录时间lasttime,getdate())>=3))
4、人物表
delete from 人物表 where 账号id in (select 账号id from 账号表 where datediff(day,上次登录时间lasttime,getdate())>=3)
5、账号表
delete from 账号表 where datediff(day,上次登录时间lasttime,getdate())>=3
公司的电商app需要做搜索功能,分析整理后列出如下需求点:
接下来就是愉悦(tongku)的设计和coding了
商品表已经在业务库中存在直接用,只需要设计出es索引就可以。es安装后顺带装上jk、pinyin插件,因为后续要用到拼音功能,不过在本阶段先不管拼音的事儿。
产品表定义:
产品类对应Repository定义:
maven-pom文件增加引用
applicationyml文件添加es相关配置
以上定义完成后,启动项目,成功后可以看到如下提示(debug级别下):
如果没有伴随出现报错信息(es索引配置有误,不能创建索引时会给出相应提示),此时es中的 product 索引应该已经成功创建了。
使用es GET /demo-product/_mapping 命令可查看索引结构已经完整创建:
索引表的插入,可使用spring-boot的@Schedule定时器,以指定间隔扫描产品表的新增数据,以es对应product表的字段封装后,插入es索引即可
此时索引表结构和数据已经准备就绪,可以开始写查询方法了!
我们先准备一些测试商品数据:
此处有一点需要注意,由于商品品牌名称大多为互相无关联意义的字组成,如果使用默认分词,会被分的很散,不符合要求,所以需要将品牌名中文部分列出来,加入到ik分词插件的扩展词典中去,此处不展开。
分析一下搜索需求,当用户传入搜索关键词后,需要在商品名称、描述、类目名称和品牌名称四个字段中做match *** 作,暂定互相之间的权重比为05:01:02:1,可使用NativeSearchQuery创建查询方法:
打开浏览器,输入 /product/风衣%20毛衣/1/10 ,可以得到如下结果:
至此,第一步工作算是暂时完成。
之前讲的搜索都是针对整个搜索词的 *** 作,只能查找倒排索引的单个词,词是最小单元,但是如果我们想寻找词的部分匹配,比如 sql 语句中的 " %value % " ,es是如何做到的呢?
在有些情况,也是部分匹配是非常有用的,比如在搜索时的自动提示、比如某些特定的不会分词的字符,邮编,产品序列号等,我们不知道全部字符,只知道该字符串的部分,该如何检索?
为了找到所有以 W1 开始的邮编,可以使用简单的 prefix 查询:
prefix查询并不会分析查询词,他只是会在倒排索引的词项列表中,搜索所有的词项,判断是否是以查询词作为前缀。
注意:
1 prefix查询并不会计算评分,所有文档评分默认为 1 ,相比较prefix过滤的不同,过滤会缓存,但是查询不会。
2 prefix查询会对给集群的带来很大压力,如果字段中词的集合很小时,可以放心使用,否则应该使用较长的前缀来限制这些影响。
与 prefix 前缀查询的特性类似, wildcard 通配符查询也是一种底层基于词的查询,与前缀查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符查询: 匹配任意字符, 匹配 0 或多个字符。
wildcard 和 regexp 查询的工作方式与 prefix 查询完全一样,它们也需要扫描倒排索引中的词列表才能找到所有匹配的词,意味着同样需要注意和前缀查询相同的性能问题。
类似于淘宝,在我们输入搜索词时,它会在搜索框下展现出搜索结果供用户选择,可以使用户在更短时间内得到搜索结果。
对于查询时的输入即搜索,可以使用 match_phrase 的一种特殊形式, match_phrase_prefix 查询:
对于以上查询,会返回 ' 麻辣小龙虾' , ' 麻辣烫 ', ' 麻辣小零食 ' 等以搜索词作为前缀的搜索结果。这种查询的行为与 match_phrase 查询一致,不同的是它将查询字符串的最后一个词作为前缀使用。同样它也支持 slop 参数,让相对位置不那么严格。
在上边的前缀搜索时,我们谈过使用前缀搜索的问题,在这里问题同样存在,也就是资源消耗问题,如果我们搜索a,索引中有成千上万个以 a 为前缀的文档,这样不仅会消耗系统资源,而且结果的用户也不大。
可以通过设置 max_expansions 参数来限制前缀扩展的影响, 该参数会设置es查询返回的文档的数量不超过该参数的值。
关于ES的搜索,小白暂且简单的归纳如下:
新增文档时涉及分词、构建索引
查询时涉及分词、查询索引、相关度评分
那么接下来,小白就从分词、索引、相关度评分三个方面开始瞎掰了
分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es里面称为Analysis。
分词机制:
Character Filter:对原始文本进行处理,例如 去除html标签、替换字符等
Tokenizer:将原始文本进行分词,例如 小白最帅 => 小白,最,帅
Token Filters:分词后的关键字进行加工,例如 转小写、删除语气词、近义词和同义词等
在进行Tokenizer之前对对原始文本进行处理,例如 去除html标签、替换字符等
不过进行处理后,会影响后续Tokenizer解析的position和offset
HTML Strip => 去除html标签和转换html实体
Mapping => 字符串替换 *** 作
Pattern Replace => 正则匹配替换
将原始文本进行分词,例如 小白最帅 => 小白,最,帅
Elasticsearch自带的分词器:
分词器(Analyzer) 特点
standard(es默认) 支持多语言,按词切分并做小写处理
simple 按照非字母切分,小写处理
whitespace 按照空格来切分
stop 去除语气助词,如the、an、的、这等
keyword 不分词
pattern 正则分词,默认\w+,即非字词符号做分割符
language 常见语言的分词器(30+)
常见中文分词器:
名称 介绍 特点
IK 实现中英文单词切分 自定义词库
>
以上就是关于Elasticsearch 查询表达式全部的内容,包括:Elasticsearch 查询表达式、espython索引保存到文件、elasticsearch基本查询笔记(三)-- es查询总结等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)