目录
一、基本查询
1. atch_all 查询
match_all
查询简单的匹配所有文档。在没有指定查询方式时,它是默认的查询:
{ "match_all": {}}
它经常与 filter 结合使用—例如,检索收件箱里的所有邮件。所有邮件被认为具有相同的相关性,所以都将获得分值为 1
的中性 _score
。
2. match 查询
在任何字段上都可进行全文搜索、精确查询
如果你在一个全文字段上使用 match
查询,在执行查询前,它将用正确的分析器去分析查询字符串:
{ "match": { "tweet": "About Search" }}
如果在一个精确值的字段上使用它,例如数字、日期、布尔或者一个 not_analyzed
字符串字段,那么它将会精确匹配给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
对于精确值的查询,你可能需要使用 filter 语句来取代 query,因为 filter 将会被缓存。
3. multi_match 查询
multi_match
查询可以在多个字段上执行相同的 match
查询:
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
4. range 查询
range
查询找出那些落在指定区间内的数字或者时间:
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
# gt 大于
# gte 大于等于
# lt 小于
# lte 小于等于
5. term 查询
term
查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed
的字符串:
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
term
查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。
6. terms 查询
terms
查询和 term
查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
和 term
查询一样,terms
查询对于输入的文本不分析。它查询那些精确匹配的值(包括在大小写、重音、空格等方面的差异)。
7. exists 查询和 missing 查询
exists
查询和 missing
查询被用于查找那些指定字段中有值 (exists
) 或无值 (missing
) 的文档。这与SQL中的 IS_NULL
(missing
) 和 NOT IS_NULL
(exists
) 在本质上具有共性:
{
"exists": {
"field": "title"
}
}
这些查询经常用于某个字段有值的情况和某个字段缺值的情况。
二、组合查询
现实的查询需求需要在多个字段上查询多种多样的文本,并且根据一系列的标准来过滤。为了构建类似的高级查询,可以用 bool
查询来实现需求。这种查询将多查询组合在一起,成为自己想要的布尔查询。
1. bool以及接收的参数
must
- 文档 必须 匹配这些条件才能被包含进来。
must_not
- 文档 必须不 匹配这些条件才能被包含进来。
should
- 如果满足这些语句中的任意语句,将增加
_score
,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
filter
- 必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
每一个子查询都独自地计算文档的相关性得分。一旦他们的得分被计算出来, bool
查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分。
下面的查询用于查找 title
字段匹配 how to make millions
并且不被标识为 spam
的文档。那些被标识为 starred
或在2014之后的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
如果没有 must
语句,那么至少需要能够匹配其中的一条 should
语句。但,如果存在至少一条 must
语句,则对 should
语句的匹配没有要求。
2. 增加带过滤器(filtering)的查询
如果不想因为文档的时间而影响得分,可以用 filter
语句来重写前面的例子:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"range": { "date": { "gte": "2014-01-01" }}
}
}
}
# range 查询已经从 should 语句中移到 filter 语句
通过将 range 查询移到 filter
语句中,将它转成不评分的查询,将不再影响文档的相关性排名。由于它现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。
所有查询都可以借鉴这种方式。将查询移到 bool
查询的 filter
语句中,这样它就自动的转成一个不评分的 filter 了。
如果需要通过多个不同的标准来过滤你的文档,bool
查询本身也可以被用做不评分的查询。简单地将它放置到 filter
语句中并在内部构建布尔逻辑:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2014-01-01" }}},
{ "range": { "price": { "lte": 29.99 }}}
],
"must_not": [
{ "term": { "category": "ebooks" }}
]
}
}
}
}
# 将 bool 查询包裹在 filter 语句中,我们可以在过滤标准中增加布尔逻辑
通过混合布尔查询,我们可以在我们的查询请求中灵活地编写 scoring 和 filtering 查询逻辑。
3. constant_score 查询
尽管没有 bool
查询使用这么频繁,constant_score
查询也是你工具箱里有用的查询工具。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。
可以使用它来取代只有 filter 语句的 bool
查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。
{
"constant_score": {
"filter": {
"term": { "category": "ebooks" }
}
}
}
# term 查询被放置在 constant_score 中,转成不评分的 filter。这种方式可以用来取代只有 filter 语句的 bool 查询。
三、通过Python查询
1. 详细代码实现如下
import unittest
# 需要导入的es包
from elasticsearch import Elasticsearch
class Demo(unittest.TestCase):
"""
定义一个基础测试类
"""
def test_get_es(self):
"""
连接es,获取一个es实体,用于后续查询
:return:
"""
host = '172.16.153.129:9200'
username = 'elastic'
password = '123456'
es = Elasticsearch(
host,
# 认证信息
http_auth=(username, password)
)
print(es.info())
return es
def test_get_es_res_by_quey(self):
"""
连接es,获取一个es实体,通过query进行查询
:return:
"""
host = '172.16.153.129:9200'
username = 'elastic'
password = '123456'
es = Elasticsearch(host, http_auth=(username, password))
print(es.info())
# 具体的query例子 在后面
query = {
'bool': {
'must_not': {'match': {'message': 'M('}},
'must': [
{'match': {'TransId': '06100021650016153'}},
{'range': {'@timestamp': {'gte': u'now-7d', 'lte': 'now'}}}
]
}
}
res = es.search(
index='logstash-2021.06.11',
body={
"query": query,
"sort": [{"@timestamp": {"order": "desc"}}]})
return res
2. 具体的一个query实例
query = { # 请求体
"query": { # 关键字,把查询语句给 query
"bool": { # 关键字,表示使用 filter 查询,没有匹配度
"must": [ # 表示里面的条件必须匹配,多个匹配元素可以放在列表里
{
"match": { # 关键字,表示需要匹配的元素
"TransId": '06100021650016153' # TransId 是字段名, 06100021650016153 是此字段需要匹配到的值
}
},
{
"match": {
"Ds": '2021-06-11'
}
},
{
"match": {
"Gy": '2021020235'
}
}, ],
"must_not": { # 关键字,表示查询的结果里必须不匹配里面的元素
"match": { # 关键字
"message": "M(" # message 字段名,这个字段的值一般是查询到的结果内容体。这里的意思是,返回的结果里不能包含特殊字符 'M('
}
}
}
},
# 下面是对返回的结果继续排序
"sort": [{"@timestamp": {"order": "desc"}}],
"from": 0, # 从匹配到的结果中的第几条数据开始返回,值是匹配到的数据的下标,从 0 开始
"size": 10 # 返回多少条数据
}