6、Elasticsearch 检索文档的方式

接着上一篇,继续梳理 ES 检索文档的两种方式,即结构化检索和全文检索。

结构化检索,建议参考官方文档:Term-level queries | Elasticsearch Guide [6.8] | Elastic

全文检索,也建议参考官方文档:Full text queries | Elasticsearch Guide [6.8] | Elastic

一、结构化检索

1、精准搜索之term/terms查询

term query 表示单个精准值查询,而 terms query 表示多个精准值查询。请注意,字段的数据类型是 text 或 keyword 类型。

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "term": {
      "pkey": "15556905959_10011" //单个精准值查询
    }
  }
}

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "terms": {
      "pkey": ["15556905959_10011","15556905756_10010"] //多个精准值查询
    }
  }
}

2、精准搜索之bool filter查询

bool query 查询选项有:must、must_not、should、filter,它们的区别如下:

  • must:所有都必须匹配,相当于and;
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "bool": {
      "must": [
        {"term": {"status": "U"}},
        {"term": {"myObj.sign_no": "10010"}}
      ]
    }
  }
}
  • must_not:所有都必须不被匹配,相当于not;
# 索引的文档,①不存在,使用must_not查询,会输出所有包含flag=0的文档
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "bool": {
      "must_not": [
         {"term": {"flag": 1}} //①
      ]
    }
  }
}
  • should:至少有一个匹配,相当于or;
# 索引的文档,①不存在,②存在一条,使用should查询会输出一条结果
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "bool": {
      "should": [
        {"term": {"flag": 1}}, //①
        {"term": {"myObj.user_id": "15556905756"}} //②
      ]
    }
  }
}
  • filter:必须匹配,运行在非评分&过滤模式。
# 索引的文档,①不存在,②存在一条,使用filter查询不到结果
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "bool": {
      "filter": [
        {"term": {"flag": 1}}, //①
        {"term": {"myObj.user_id": "15556905756"}} //②
      ]
    }
  }
}

3、前缀搜索(prefix query)

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "prefix": {
      "myObj.user_id": "155" //匹配 myObj.user_id 前缀包含155字符串的文档
    }
  }
}

4、模糊搜索(fuzzy query)

查找在模糊度中指定的最大编辑距离内的所有可能匹配项,再检查术语字典,以找出在索引中实际存在待检索的关键词:

# 索引中存在一条pkey=15556905954_10010的文档
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "fuzzy": {
       //"pkey": "15556905954" //匹配找不到对应结果
       //"pkey": "15556905954_10" //仍然匹配找不到对应结果 
         "pkey": "15556905954_1001"
    }
  }
}

5、范围搜索(range query)

适合数值类型的字段进行范围查询,范围比较的关键字有:

  • gt: > 大于(greater than)
  • lt: < 小于(less than)
  • gte: >= 大于或等于(greater than or equal to)
  • lte: <= 小于或等于(less than or equal to)
# 查询 myObj.pay_amount 的支付金额值,范围为[20,50)
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
   "query": {
       "range": {
           "myObj.pay_amount": {
                "gte": "20",
                "lt": "50"
            }
        }  
    }
}

# 多个字段值得范围查询
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
        "bool": {
            "filter": [
                {
                  "range": {
                        "myObj.pay_amount": {
                            "gte": "20",
                            "lt": "50"
                        }
                    }
                },
                {
                  "range": {
                        "myObj.pay_amount1": {
                            "gte": "30",
                            "lte": "45"
                        }
                    }
                }
            ]
        }
    }
}

6、通配符搜索(wildcard query)

通配符有:* 表示匹配任何字符序列(包括空字符序列)?表示匹配任何单个字符

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "wildcard": {
      "myObj.user_id": "155*"
    }
  }
}

7、类型搜索(type query)

在 8.x 版本中已不再支持 type query 。

# 返回指定type的文档信息
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
   "query": {
        "type": {
            "value":"_doc"
        }
    }
}

8、存在搜索(exists query)

查询某个或多个字段是否存在:

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "exists": {
       "field": "collection_url"
    }
  }
}

GET mytest_index_0626/_search?pretty&track_total_hits=true
{
  "query": {
    "bool": {
      "filter": [
        {"exists": {"field": "status"}},
        {"exists": {"field": "collection_url"}}
      ]
    }
  }
}

请注意,如果查询字段不存在,可以使用前面的 must_not 实现

另外,如果要求 exists 查询能匹配到 null 类型,需要设置mapping,以 status 字段为例:

"status": {
    "type": "keyword",
    "null_value": "_null_"
}

9、正则搜索(regexp query)

使用.*?+通配符查询的正则检索,性能是会非常低的。

# 返回指定id的文档信息
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
    "query": {
        "regexp": {
            "collection_url":"https.*/hangzhou/"
        }
    }
}

10、id 搜索(ids query)

# 返回指定id的文档信息
GET mytest_index_0626/_search?pretty&track_total_hits=true
{
    "query": {
        "ids": {
            "type": "_doc",
            "values":["axEwmoEBTXtCd1dvuDqv","gxHImYEBTXtCd1dv3Dfj"]
        }
    }
}

二、全文检索

我们知道 keyword 类型不支持分词,该类型的字段使用全文检索时,必须使用全部字符串匹配才能被查找到;而 text 类型的字段适合于全文检索,支持分词,同时要考虑具体分词器,因为不同的分词器对相同的文本字符长的分解词项可能不一样。

下面使用 wheater_infos_2022 索引演示,在该索引里新增了6.1号~6.3号、四座城市的共12条天气记录数据~

1、匹配搜索(match query)

match 匹配查询,查询时会分词处理,接受文本/数字/日期等数据类型。

# today_weather.temperature_range,该字段是text类型
# temperature_range 原文本字符串为"26-344℃",此处会使用到默认的standard分词方式
# 匹配 today_weather.temperature_range 包含 26 或 44
GET wheater_infos_2022/_search?pretty&track_total_hits=true
{
   "query": {
        "match": {
            "today_weather.temperature_range": "26 44"
        }
    }
}

# 上面的写法看不明白?上面的写法等同于下面的这种写法:
GET wheater_infos_2022/_search?pretty&track_total_hits=true
{
   "query": {
        "match": {
            "today_weather.temperature_range": {
                "query": "26 44",
                "operator": "or" //默认or操作
            }
        }
    }
}

如果需要了解更多的参数设置(比如 fuzziness/zero_terms_query/cutoff_frequency 等),可参考官网文档:Match Query | Elasticsearch Guide [6.8] | Elastic

2、匹配解析搜索(match_phrase query)

match_phrase 查询分析文本,并从分析文本中创建分词(该查询方式,首先将查询的文本字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含全部搜索词项,且位置与搜索词项相同的文档)。

请注意,这句话的理解,只保留那些包含全部搜索词项,位置与搜索词项相同的文档,也就是说,我把 today_weather.temperature_range 的 "26 344",修改成 "344 26",返回查询的结果则会为空。

GET wheater_infos_2022/_search?pretty&track_total_hits=true
{
    "query": {
        "match_phrase": {
            "today_weather.temperature_range": "26 344" 
        }
    }
}

如果需要了解更多的参数设置(比如 analyzer),可参考官网文档:Match Phrase Query | Elasticsearch Guide [6.8] | Elastic

3、匹配解析前缀搜索(match_phrase_prefix query)

match_phrase_prefix 与 match_phrase 原理相同,不同的是 match_phrase_prefix 允许文本中最后一个术语可以前缀匹配。

GET wheater_infos_2022/_search?pretty&track_total_hits=true
{
   "query": {
        "match_phrase_prefix": {
            "today_weather.temperature_range": "34*" 
        }
    }
}

如果需要了解更多的参数设置(比如 max_expansions),可参考官网文档:Match Phrase Prefix Query | Elasticsearch Guide [6.8] | Elastic

4、多字段匹配搜索(multi_math query)

multi_math 能在多个字段上反复执行相同的查询。默认情况下,查询的类型是 best_fields(它会为每个字段生成一个 match 查询),也支持 most_fields、cross_fields、phrase、phrase_prefix 等查询类型。

GET wheater_infos_2021/_search?pretty&track_total_hits=true
{
   "query": {
        "multi_match": {
           "query": "26 AND 344", //查询字符串,支持指定AND | OR | NOT条件
            "fields": [
                "today_weather.temperature",
                "today_weather.temperature_*",
                "today_weather.pm_value^2" //^2表示提示查询该字段的权重
            ]
        }
    }
}

如果需要了解更多的参数设置(比如 type/tie_breaker 等),可参考官网文档:Multi Match Query | Elasticsearch Guide [6.8] | Elastic

5、匹配搜索(query_string query)

query_string 许在单个查询字符串中指定AND | OR | NOT条件,同时也和 multi_match query 一样,支持多字段搜索。

请注意,query_string 不支持 keyword 类型字段查询,返回的查询结果则为空,query_string 适用于查询 text 类型的字段,且查询的分词和顺序无关,分词也不需要连续,比如 "query" 使用 "26 AND 344"  和  "344 AND 26" 查询效果是一样的!

GET wheater_infos_2021/_search?pretty&track_total_hits=true
{
   "query": {
        "query_string": {
            "query": "26 AND 344", //查询字符串,支持指定AND | OR | NOT条件
            "fields": [
                "today_weather.temperature"
            ]
        }
    }
}


GET wheater_infos_2021/_search?pretty&track_total_hits=true
{
   "query": {
        "query_string": {
            "query": "26 AND 344", //查询字符串,支持指定AND | OR | NOT条件
            "fields": [
                "today_weather.temperature",
                "today_weather.temperature_*",
                "today_weather.pm_value^2" //^2表示提示查询该字段的权重
            ]
        }
    }
}

如果需要了解更多的参数设置,可参考官网文档:Query String Query | Elasticsearch Guide [6.8] | Elastic

6、简单字符串搜索(simple_query_string query)

与 query_string 相比,simple_query_string 不会抛出异常,并丢弃查询的无效部分,不支持使用 AND、OR、NOT 作为连接符,而是支持下面这些方式:

  • + 表示与运算,相当于query_string 的 AND;
  • | 表示或运算,相当于query_string  的 OR(默认);
  • - 表示取反运算,相当于query_string 的 NOT;
  • "" 表示对检索词进行 match_phrase query;
  • * 字词末尾表示前缀查询;
  • ( and )表示优先级;
GET wheater_infos_2021/_search?pretty&track_total_hits=true
{
    "query": {
        "simple_query_string": {
            "query": "26 + 34", //查询字符串,+相当于query_string的AND
            "fields": [
                "today_weather.temperature",
                "today_weather.temperature_*",
                "today_weather.pm_value^2" //^2表示提示查询该字段的权重
            ]
        }
    }
}

如果需要了解更多的参数设置,可参考官网文档:Simple Query String Query | Elasticsearch Guide [6.8] | Elastic

最后

随着 ES 版本不断的更新,term-level queries 和 full-text queries 也在调整文档查询方式。比如,与 6.8 版本相比,在最新版本的 8.x 中,term-level queries 不再支持 type query,新增支持 terms_set query;又比如,full-text queries 与 6.8 版本相比新增了 intervals query、match_bool_prefix query、combined_fields query 等类型的查询。因此,平时要注意,根据自己当前使用的 ES 版本,并结合官方文档加以学习和使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值