关于Elasticsearch查找相关的问题汇总(match、match_phrase、query_string和term)
关于Elasticsearch查找相关的问题汇总(match、match_phrase、query_string和term)
查询全部:
{
"query": {
"match_all": {}
}
}
对应的 QueryBuilder Class 为 MatchAllQueryBuilder
具体方法为 QueryBuilders.matchAllQuery() {
"query": {
"match": {
"orderEventDispatchStatusDTO.consoleOperatorName": "李龙1"
}
}
}
对应的 QueryBuilder class : MatchQueryBuilder
具体方法 : QueryBuilders.matchQuery() Search Query QueryBuilder Class Method in QueryBuilders
Match MatchQueryBuilder QueryBuilders.matchQuery()
Match Phrase MatchPhraseQueryBuilder QueryBuilders.matchPhraseQuery()
Match Phrase Prefix MatchPhrasePrefixQueryBuilder QueryBuilders.matchPhrasePrefixQuery()
Multi Match MultiMatchQueryBuilder QueryBuilders.multiMatchQuery()
Common Terms CommonTermsQueryBuilder QueryBuilders.commonTermsQuery()
Query String QueryStringQueryBuilder QueryBuilders.queryStringQuery()
Simple Query StringSimpleQueryStringBuilder QueryBuilders.simpleQueryStringQuery() 基于词项的查询
Term
term 查询可用作精确值匹配,精确值的类型则可以是数字,时间,布尔类型,或者是那些 not_analyzed 的字符串。
对应的 QueryBuilder class 是 TermQueryBuilder
具体方法是 QueryBuilders.termQuery() Terms
terms 查询允许指定多个值进行匹配。如果这个字段包含了指定值中的任何一个值,就表示该文档满足条件。
对应的 QueryBuilder class 是 TermsQueryBuilder
具体方法是 QueryBuilders.termsQuery() Wildcard
wildcard 通配符查询是一种底层基于词的查询,它允许指定匹配的正则表达式。而且它使用的是标准的 shell 通配符查询: ? 匹配任意字符
* 匹配 0 个或多个字符
wildcard 需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID。
由于通配符和正则表达式只能在查询时才能完成,因此查询效率会比较低,在需要高性能的场合,应当谨慎使用。
对应的 QueryBuilder class 是 WildcardQueryBuilder
具体方法是 QueryBuilders.wildcardQuery() Search Query QueryBuilder Class Method in QueryBuilders
Term TermQueryBuilder QueryBuilders.termQuery()
Terms TermsQueryBuilder QueryBuilders.termsQuery()
Range RangeQueryBuilder QueryBuilders.rangeQuery()
Exists ExistsQueryBuilder QueryBuilders.existsQuery()
Prefix PrefixQueryBuilder QueryBuilders.prefixQuery()
Wildcard WildcardQueryBuilder QueryBuilders.wildcardQuery()
Regexp RegexpQueryBuilder QueryBuilders.regexpQuery()
Fuzzy FuzzyQueryBuilder QueryBuilders.fuzzyQuery()
Type TypeQueryBuilder QueryBuilders.typeQuery()
Ids IdsQueryBuilder QueryBuilders.idsQuery() 复合查询
什么是复合查询?
复合查询会将其他的复合查询或者叶查询包裹起来,以嵌套的形式展示和执行,得到的结果也是对各个子查询结果和分数的合并。可以分为下面几种: constant_score query 经常用在使用 filter 的场合,所有匹配的文档分数都是一个不变的常量
类-方法:Constant Score ConstantScoreQueryBuilder QueryBuilders.constantScoreQuery() bool query可以将多个叶查询和组合查询再组合起来,可接受的参数如下
must: 文档必须匹配这些条件才能被包含进来
must_not 文档必须不匹配才能被包含进来
should 如果满足其中的任何语句,都会增加分数;即使不满足,也没有影响
filter 以过滤模式进行,不评分,但是必须匹配
类-方法:Bool BoolQueryBuilder QueryBuilders.boolQuery() dis_max query
叫做分离最大化查询,它会将任何与查询匹配的文档都作为结果返回,但是只是将其中最佳匹配的评分作为最终的评分返回。
类-方法: Dis Max DisMaxQueryBuilder QueryBuilders.disMaxQuery() function_score query
允许为每个与主查询匹配的文档应用一个函数,可用来改变甚至替换原始的评分
类-方法:Function Score FunctionScoreQueryBuilder QueryBuilders.functionScoreQuery() boosting query
用来控制(提高或降低)复合查询中子查询的权重。
类-方法:Boosting BoostingQueryBuilder QueryBuilders.boostingQuery() 特殊查询
Wrapper Query
这里比较重要的一个是 Wrapper Query,是说可以接受任何其他 base64 编码的字符串作为子查询。
主要应用场合就是在 Rest High-Level REST client 中接受 json 字符串作为参数。比如使用 gson 等 json 库将要查询的语句拼接好,直接塞到 Wrapper Query 中查询就可以了,非常方便。 Wrapper Query 对应的 QueryBuilder class 是 WrapperQueryBuilder
具体方法是 QueryBuilders.wrapperQuery() 一)text字段和keyword字段的区别
所以将字段设置成keyword的时候查询的时候已有的值不会被分词。而text类型的字段会被分词,查询的时候如果用拆开查可以查询的到,但是要是直接全部查,就是查询不到。
注意“1, 2”会被拆分成[1, 2],但是"1,2"是不拆分的,少了个空格。 一、match、match_phrase、query_string和term的区别
1、match和term的区别
1.1、term
1)term查询keyword字段。
term不会分词。而keyword字段也不分词。需要完全匹配才可。 2)term查询text字段
因为text字段会分词,而term不分词,所以term查询的条件必须是text字段分词后的某一个。 1.2.match
1)match查询keyword字段
match会被分词,而keyword不会被分词,match的需要跟keyword的完全匹配可以。
其他的不完全匹配的都是失败的。 2)match查询text字段
match分词,text也分词,只要match的分词结果和text的分词结果有相同的就匹配。 1.3.match_phrase
1)match_phrase匹配keyword字段。
这个同上必须跟keywork一致才可以。 2)match_phrase匹配text字段。
match_phrase是分词的,text也是分词的。match_phrase的分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。 1.4.query_string
1)query_string查询keyword类型的字段,试过了,无法查询。 2)query_string查询text类型的字段。
和match_phrase区别的是,不需要连续,顺序还可以调换。 二、关于Elasticsearch的精确值查找(term)不生效问题
2.1、问题
常用的 term 查询, 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。term查询数字的时候并没有什么问题,但是当我们对字符串类型的字段进行term查询时可能会得到意想不到的情况,可能明明有记录却查询不到,也可能查询出不符合预期的记录。
原因
ES会默认给每个字段进行分词然后建立倒排索引。比如,有两条JSON数据如下:
[
{
"id" : 1
"searchField" : "abc#def"
},
{
"id" : 2
"searchField" : "abc#xyz"
}
]
使用ES提供的analyze API 可以看到分词结果如下: 按照上面的分词结果,那么当我们将这两条数据插入ES的时候,建立的倒排索引如下:
Term Counter DocId
abc 2 1,2
def 1 1
xyz 1 2
注意:如果字段内容是大写的,那么在分词生成索引后,索引的项目会变成小写,比如上面的两条数据是ABC#DEF和ABC#XYZ,那么生成的索引也和上面的一样。此时由于索引项是小写,因此term查询ABC是查不到的,必须要查询abc;match查询ABC是可以查询到的,因为match会进行分词然后再匹配。 ①使用term精确查询searchField为abc#def的记录:
{
"query": {
"term": {
"searchField":"abc#def"
}
}
}
此时得到的结果是空,我们无法获得期望的结果,问题不在 term 查询,而在于abc#def并不在我们的倒排索引中。 ②使用term精确查询searchField为abc的记录:
{
"query": {
"term": {
"searchField":"abc"
}
}
}
此时得到的结果是两条数据都被检索出来。
根据建立的倒排索引不难发现,当精确匹配abc时,那么会命中如下的索引,它的DocId是1,2,因此会查出两条记录。 解决方案
①将字段的type设置为keyword
明确字段是否需要分词,不需要分词的字段就将type设置为keyword,可以节省空间和提高写性能。
ElasticSearch 5.0以后,String字段被拆分成两种新的数据类型: text用于全文搜索,会分词,而keyword用于关键词搜索,不进行分词。对于字符串类型的字段,ES默认会再生成一个keyword字段用于精确索引。默认mapping如下:
"mapping": {
"properties": {
"id": {
"type": "long"
},
"searchField": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
②将该字段设置成 not_analyzed 无需分析的
告诉 Elasticsearch该字段具有精确值,要将index属性设置成 not_analyzed 无需分析的。也是在mapping中进行设置,例如:
"mapping": {
"properties": {
"id": {
"type": "long"
},
"searchField": {
"type": "text",
"index": "not_analyzed"
}
}
如果是使用Java High Level REST Client 操作Elasticsearch的话可以参考官方API进行设置。 例如:
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.startObject("properties");
{
builder.startObject("message");
{
builder.field("type", "text");
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
request.source(builder); index 属性控制怎样索引字符串。它可以是下面三个值:
① analyzed:首先分析字符串,然后索引它。换句话说,以全文索引这个域。
② not_analyzed:索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
③ no:不索引这个域。这个域不会被搜索到。
注意:其他简单类型(例如 long , double , date 等)也接受 index 参数,但有意义的值只有 no 和 not_analyzed , 因为它们永远不会被分析。 2.2、elasticsearch大小写无法使用term查询的问题
在 Elasticsearch 中处理字符串类型的数据时,如果我们想把整个字符串作为一个完整的 term 存储,我们通常会将其类型 type 设定为 keyword。但有时这种设定又会给我们带来麻烦,比如同一个数据再写入时由于没有做好清洗,导致大小写不一致,比如 apple、Apple两个实际都是 apple,但当我们去搜索 apple时却无法返回 Apple的文档。
原因是elasticsearch在创建倒排索引时,就已经将大写转为小写,而后写入索引。解决方法:
一种是在传入查询条件的时候,使用toLowerCase()转化为小写,但是条件一多,代码量颇多,不太适用。
一种是在设置mapping的时候设置normalizer要解决这个问题。 PUT test_normalizer{
"mappings": {
"doc":{
"properties": {
"type":{
"type":"keyword"
}
}
}
}
}
PUT test_normalizer/doc/1{
"type":"apple"}
PUT test_normalizer/doc/2{
"type":"Apple"}
# 查询一 GET test_normalizer/_search{
"query": {
"match":{
"type":"apple"
}
}
}
# 查询二GET test_normalizer/_search{
"query": {
"match":{
"type":"aPple"
}
}}
原因:
Docs写入 Elasticsearch时由于 type是 keyword,分词结果为原始字符串
查询 Query 时分词默认是采用和字段写时相同的配置,因此这里也是 keyword,因此分词结果也是原始字符
两边的分词进行匹对,便得出了我们上面的结果 2. Normalizer
normalizer是 keyword的一个属性,可以对 keyword生成的单一 Term再做进一步的处理,比如 lowercase,即做小写变换。使用方法和自定义分词器有些类似,需要自定义,如下所示: DELETE test_normalizer
# 自定义 normalizer
PUT test_normalizer{
"settings": {
"analysis": {
"normalizer": {
"lowercase": {
"type": "custom",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"doc": {
"properties": {
"type": {
"type": "keyword"
},
"type_normalizer": {
"type": "keyword",
"normalizer": "lowercase"
}
}
}
}}
PUT test_normalizer/doc/1{
"type": "apple",
"type_normalizer": "apple"}PUT test_normalizer/doc/2{
"type": "Apple",
"type_normalizer": "Apple"}
# 查询三GET test_normalizer/_search{
"query": {
"term":{
"type":"aPple"
}
}}
# 查询四GET test_normalizer/_search{
"query": {
"term":{
"type_normalizer":"aPple"
}
}} 我们第一步是自定义了名为 lowercase的 normalizer,其中filter 类似自定义分词器中的 filter ,但是可用的种类很少,详情大家可以查看官方文档。然后通过 normalizer属性设定到字段type_normalizer中,然后插入相同的2条文档。执行发现,查询三无结果返回,查询四返回2条文档。 文档写入时由于加入了 normalizer,所有的 term都会被做小写处理
查询时搜索词同样采用有 normalizer的配置,因此处理后的 term也是小写的
两边分词匹对,就得到了我们上面的结果 ### 扩展
"brandTxt": {
"type": "text",
"analyzer": "ik_max_word"
},
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"address": {
"type": "text",
"analyzer": "ik_max_word",
"include_in_all": false
},
"typeTxt": {
"type": "text",
"analyzer": "ik_max_word"
},
关于Elasticsearch查找相关的问题汇总(match、match_phrase、query_string和term)的更多相关文章
- jQuery实现页内查找相关内容
当需要在页面中查找某个关键字时,一是可以通过浏览器的查找功能实现,二是可以通过前端脚本准确查找定位,本文介绍通过jQuery实现的页面内容查找定位的功能,并可扩展显示查找后的相关信息. 本文以查找车站 ...
- Android UI相关开源项目库汇总
最近做了一个Android UI相关开源项目库汇总,里面集合了OpenDigg 上的优质的Android开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个st ...
- Elasticsearch及相关插件的安装
Elasticsearch及相关插件的安装 1.安装Elasticsearch并启动服务 2.安装第三方插件 2.1.Head插件 是Elasticsearch的一个集群管理工具,可以通过它来查看和搜 ...
- Linux&Android相关常用命令汇总记录
Linux&Android相关常用命令汇总记录 0@Linux&Android系统命令行下如何查看命令的帮助信息: command --help 1@在Linux系统中,设备分为三类, ...
- java OOP及相关基础知识汇总(转)
OOP 对象有三个要素 behavior 接口是怎样的,有什么方法/field可以用? state 调用方法的时候,对象会有什么反应? 只有通过调用方法才能改变一个对象的state identity ...
- java操作elasticsearch实现条件查询(match、multiMatch、term、terms、reange)
1.条件match query查询 //条件查询match query @Test public void test10() throws UnknownHostException { //1.指定e ...
- 如何在集合中巧用Where来查找相关元素
在我们的项目中我们经常会查找一些集合中的重要元素,当然我们可以使用常规的foreach循环和if语句来查询,但是我们要学会使用System.Linq命名空间下面的静态类Enumerable下面的静态方 ...
- Elasticsearch查询规则(一)match和term
es种有两种查询模式,一种是像传递URL参数一样去传递查询语句,被称为简单搜索或查询字符串(query string)搜索,比如 GET /megacorp/employee/_search //查询 ...
- Linux中3个文件查找相关命令详解
源于:https://mp.weixin.qq.com/s/VPs-IXY6RoxbltHIxtIbng which命令 我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令 ...
- elasticsearch相关概念及常用操作汇总
背景 我本来是想把我的写的es的平时总结dsl发出来的,但是我发现只搞那个意义大不.干脆多写点吧. 索引的结构化和非结构 我们经常用数据库,当然会经常用到索引. 然后从索引的维度去分析,系统分为结构化 ...
随机推荐
- 基于 RocketMQ Prometheus Exporter 打造定制化 DevOps 平台
简介: 本文将对 RocketMQ-Exporter 的设计实现做一个简单的介绍,读者可通过本文了解到 RocketMQ-Exporter 的实现过程,以及通过 RocketMQ-Exporter 来 ...
- 全球首款乘云而来的存储产品CDS诞生!
9月22日,阿里云发布全球首款"云定义存储"(Cloud Defined Storage,CDS)产品.作为一款本地部署的分布式存储产品,阿里云CDS拥有与公共云存储相同的技术架 ...
- [FAQ] ErrorException of l5-swagger:generate, Required @OA\Info() not found
l5-swagger 除了要添加 @OA\Get() 针对方法的注释之外,每个 Controller 还需要一个概述信息,如下: /** * @OA\Info( * title="Auth ...
- dotnet 谨慎在静态构造函数里使用锁
在 dotnet 的最佳实践里面,不推荐在静态构造函数里面包含复杂的逻辑,其中也就包含了本文聊的和多线程相关的锁的使用.最佳做法是尽量不要在静态构造函数里面碰到任何和锁以及多线程安全相关的逻辑.本文来 ...
- Git:如何撤销已经提交的代码
日常操作流程 本地工作区(尚未暂存) ---> add . 到暂存区 ---> commit 到本地仓库 ---> pull拉取关联远程仓库分支合并到本地的分支---> pus ...
- gin-vue-admin开发教程 02 了解项目目录结构和代码执行的流程
学习目标: 介绍项目 项目目录(2.0) 后台的启动过程 前台的启动过程 前后台交互的流程 视频学习地址: https://www.bilibili.com/video/BV1Rz4y1X7Zr (海 ...
- istio sidecar 工作方式
istio 是什么 Istio 是一个开放源代码的服务网格,它为基于微服务的应用程序提供了一种统一的方式来连接.保护.监控和管理服务.Istio 主要解决的是在微服务架构中的服务间通信的复杂性问题,它 ...
- d3d12龙书阅读----绘制几何体(上) 课后习题
d3d12龙书阅读----绘制几何体(上) 课后习题 练习1 完成相应的顶点结构体的输入-布局对象 typedef struct D3D12_INPUT_ELEMENT_DESC { 一个特定字符串 ...
- WPF中 x:Name和Name的区别
x:Name 唯一地标识 XAML 定义的对象,以便于从代码隐藏或通用代码中访问对象图中实例化的对象.x:Name 一旦应用于支持编程模型,便可被视为与由构造函数返回的用于保存对象引用或实例的变量等效 ...
- NOIP模拟64
T1 三元组 解题思路 一看题面,好像是一道数学题,但不完全是,或者说根本不是... 比较好想到的是 \(\mathcal{O}(n^2)\) 和 \(\mathcal{O}(nk)\) 的做法,然后 ...