elasticsearch——入门

elasticsearch 学习整理

索引和值:增删查改

In [2]: from elasticsearch import Elasticsearch
    
In [8]: es = Elasticsearch([{'host':'192.168.3.215','port':9215}])

# 创建索引
In [11]: res = es.indices.create(index='wl_test')

In [12]: print(res)
{'acknowledged': True, 'shards_acknowledged': True, 'index': 'wl_test'}

# 重复创建索引,报错 400
RequestError: RequestError(400, 'resource_already_exists_exception', 'index [wl_test/CEwdWyvfSzO4oQVpafZpsg] already exists')

# ignore 参数,忽略 400 不会报错
In [15]: es.indices.create(index='wl_test',ignore=[400])
Out[15]:
{'error': {'root_cause': [{'type': 'resource_already_exists_exception',
    'reason': 'index [wl_test/CEwdWyvfSzO4oQVpafZpsg] already exists',
    'index_uuid': 'CEwdWyvfSzO4oQVpafZpsg',
    'index': 'wl_test'}],
  'type': 'resource_already_exists_exception',
  'reason': 'index [wl_test/CEwdWyvfSzO4oQVpafZpsg] already exists',
  'index_uuid': 'CEwdWyvfSzO4oQVpafZpsg',
  'index': 'wl_test'},
 'status': 400}

# 删除索引
In [16]: es.indices.delete(index='wl_test')
Out[16]: {'acknowledged': True}
    
# 重复删除索引,报错 404
NotFoundError: NotFoundError(404, 'index_not_found_exception', 'no such index [wl_test]', wl_test, index_or_alias)
    
# ignore 参数,忽略 404 不会报错
In [18]: es.indices.delete(index='wl_test',ignore=[404])
Out[18]:
{'error': {'root_cause': [{'type': 'index_not_found_exception',
    'reason': 'no such index [wl_test]',
    'index_uuid': '_na_',
    'resource.type': 'index_or_alias',
    'resource.id': 'wl_test',
    'index': 'wl_test'}],
  'type': 'index_not_found_exception',
  'reason': 'no such index [wl_test]',
  'index_uuid': '_na_',
  'resource.type': 'index_or_alias',
  'resource.id': 'wl_test',
  'index': 'wl_test'},
 'status': 404}

# 我们需要善用 ignore 参数,把一些意外情况排除,这样可以保证程序的正常执行而不会中断。

# 插入数据
IIn [20]: data = {'title':'测试','q':"what's your name?"}

In [21]: res = es.create(index= 'wl_test',doc_type='data',id = 1,body=data)

DeprecationWarning: The 'body' parameter is deprecated for the 'create' API and will be removed in a future version. Instead use the 'document' parameter. See https://github.com/elastic/elasticsearch-py/issues/1698 for more information
d:\python36\lib\site-packages\elasticsearch\connection\base.py:209: ElasticsearchWarning: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
  warnings.warn(message, category=ElasticsearchWarning)

In [25]: res = es.create(index= 'wl_test',doc_type='data',id = 2,document=data)

ElasticsearchWarning: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).warnings.warn(message, category=ElasticsearchWarning)

In [26]: res
Out[26]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '2',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 1,
 '_primary_term': 1}

# create 方法插入数据,创建文档必须有 id
In [27]: res = es.create(index= 'wl_test',doc_type='data',document=data)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-761089aab424> in <module>
----> 1 res = es.create(index= 'wl_test',doc_type='data',document=data)

d:\python36\lib\site-packages\elasticsearch\client\utils.py in _wrapped(*args, **kwargs)
    299                 if p in kwargs:
    300                     params[p] = kwargs.pop(p)
--> 301             return func(*args, params=params, headers=headers, **kwargs)
    302
    303         return _wrapped

TypeError: create() missing 1 required positional argument: 'id'
        
# index 方法,插入数据,不用指定 id,随机id;create 方法 是对 index 方法的封装。
In [28]: es.index(index='wl_test',doc_type='data',body= data)

Out[28]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': 'JouMRX0Bd_s0QCOkwdWF',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 2,
 '_primary_term': 1}

# update 更新数据
# 注意 body 参数,我们需要添加 doc 或者 script 变量来指定修改的内容
In [45]: data={'doc':{'title':'aaa','q':'bbb'}}

In [46]: es.update(index='wl_test',doc_type='data',body=data,id=1)

# _version 字段 版本号,每次更新都 +1
Out[46]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '1',
 '_version': 2,
 'result': 'updated',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 3,
 '_primary_term': 1}

# updat 不存在的 id
NotFoundError: NotFoundError(404, 'document_missing_exception', '[data][10]: document missing')
    
# index 更新,如果 id 存在则创建

In [48]: es.index(index='wl_test',doc_type='data',body=data,id = 10)
Out[48]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '10',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 4,
 '_primary_term': 1}

In [49]: es.index(index='wl_test',doc_type='data',body=data,id = 10)
Out[49]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '10',
 '_version': 2,
 'result': 'updated',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 5,
 '_primary_term': 1}

# delete 删除数据, result 字段为 deleted,代表删除成功,_version 变成了 3,又增加了 1。
In [50]: es.delete(index='wl_test',doc_type='data',id=10)

Out[50]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '10',
 '_version': 3,
 'result': 'deleted',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 6,
 '_primary_term': 1}

# 重新创建,_version +1
In [51]: es.index(index='wl_test',doc_type='data',id=10,document=data)

Out[51]:
{'_index': 'wl_test',
 '_type': 'data',
 '_id': '10',
 '_version': 4,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 2, 'failed': 0},
 '_seq_no': 7,
 '_primary_term': 1}


# 查询数据:对于中文需要安装中文分词插件
#  elasticsearch-analysis-ik,GitHub 链接为:https://github.com/medcl/elasticsearch-analysis-ik,这里我们使用 Elasticsearch 的另一个命令行工具 elasticsearch-plugin 来安装,这里安装的版本是 6.2.4,请确保和 Elasticsearch 的版本对应起来,命令如下:
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.3.0/elasticsearch-analysis-ik-7.3.0.zip

# 查看是否中文分词器安装成功
[root@b4de731914a2 elasticsearch]# /usr/share/elasticsearch/bin/elasticsearch-plugin list
analysis-ik

# 安装之后重新启动 Elasticsearch 就可以了,它会自动加载安装好的插件。
# 首先我们新建一个索引并指定需要分词的字段
In [73]: mapping
Out[73]:
{'properties': {'title': {'type': 'text',
   'analyzer': 'ik_max_word',
   'search_analyzer': 'ik_max_word'}}}

es.indices.create(index='news', ignore=400)
# 更新 mapping
result = es.indices.put_mapping(index='news', doc_type='politics', body=mapping)

# 插入数据
datas = [
    {
        'title': '美国留给伊拉克的是个烂摊子吗',
        'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
        'date': '2011-12-16'
    },
    {
        'title': '公安部:各地校车将享最高路权',
        'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
        'date': '2011-12-16'
    },
    {
        'title': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
        'url': 'https://news.qq.com/a/20111216/001044.htm',
        'date': '2011-12-17'
    },
    {
        'title': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
        'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
        'date': '2011-12-18'
    }
]
 
for data in datas:
    es.index(index='news', doc_type='politics', body=data)

查询:

In [74]: es.search(index='wl_test',doc_type='data')
d:\python36\lib\site-packages\elasticsearch\connection\base.py:209: ElasticsearchWarning: [types removal] Specifying types in search requests is deprecated.
  warnings.warn(message, category=ElasticsearchWarning)
Out[74]:
{'took': 54,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 4, 'relation': 'eq'},
  'max_score': 1.0,
  'hits': [{'_index': 'wl_test',
    '_type': 'data',
    '_id': 'wVk5Rn0BM5UnHl8RH9ZL',
    '_score': 1.0,
    '_source': {'title': '美国留给伊拉克的是个烂摊子吗',
     'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
     'date': '2011-12-16'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'wlk5Rn0BM5UnHl8RINYy',
    '_score': 1.0,
    '_source': {'title': '公安部:各地校车将享最高路权',
     'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
     'date': '2011-12-16'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'w1k5Rn0BM5UnHl8RINZK',
    '_score': 1.0,
    '_source': {'title': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
     'url': 'https://news.qq.com/a/20111216/001044.htm',
     'date': '2011-12-17'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'xFk5Rn0BM5UnHl8RINZe',
    '_score': 1.0,
    '_source': {'title': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
     'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
     'date': '2011-12-18'}}]}}

In [75]: es.search(index='wl_test')
Out[75]:
{'took': 7,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 4, 'relation': 'eq'},  # 结果数量
  'max_score': 1.0,  # 最大匹配分数
  'hits': [{'_index': 'wl_test',
    '_type': 'data',
    '_id': 'wVk5Rn0BM5UnHl8RH9ZL',
    '_score': 1.0,
    '_source': {'title': '美国留给伊拉克的是个烂摊子吗',
     'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
     'date': '2011-12-16'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'wlk5Rn0BM5UnHl8RINYy',
    '_score': 1.0,
    '_source': {'title': '公安部:各地校车将享最高路权',
     'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
     'date': '2011-12-16'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'w1k5Rn0BM5UnHl8RINZK',
    '_score': 1.0,
    '_source': {'title': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
     'url': 'https://news.qq.com/a/20111216/001044.htm',
     'date': '2011-12-17'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'xFk5Rn0BM5UnHl8RINZe',
    '_score': 1.0,
    '_source': {'title': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
     'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
     'date': '2011-12-18'}}]}}

In [76]: dsl = {  # 通过 DSL 查询
    ...: 'query':{
    ...: 'match':{
    ...: 'title':'中国 领事馆'
    ...: }
    ...: }
    ...: }
    
In [77]: es.search(index='wl_test',doc_type='data',body=dsl)
D:\python36\Scripts\ipython:1: DeprecationWarning: The 'body' parameter is deprecated for the 'search' API and will be removed in a future version. Instead use API parameters directly. See https://github.com/elastic/elasticsearch-py/issues/1698 for more information
d:\python36\lib\site-packages\elasticsearch\connection\base.py:209: ElasticsearchWarning: [types removal] Specifying types in search requests is deprecated.
  warnings.warn(message, category=ElasticsearchWarning)
Out[77]:
{'took': 30,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 2, 'relation': 'eq'},
  'max_score': 3.9923213,
  'hits': [{'_index': 'wl_test',
    '_type': 'data',
    '_id': 'xFk5Rn0BM5UnHl8RINZe',
    '_score': 3.9923213,
    '_source': {'title': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
     'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
     'date': '2011-12-18'}},
   {'_index': 'wl_test',
    '_type': 'data',
    '_id': 'w1k5Rn0BM5UnHl8RINZK',
    '_score': 0.642793,
    '_source': {'title': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
     'url': 'https://news.qq.com/a/20111216/001044.htm',
     'date': '2011-12-17'}}]}}

# 检索时会对对应的字段全文检索,结果还会按照检索关键词的相关性进行排序,这就是一个基本的搜索引擎雏形。

mapping 类型

属性名字 说明

text 用于全文索引,该类型的字段将通过分词器进行分词,最终用于构建索引

keyword 不分词,只能搜索该字段的完整的值,只用于 filtering

long 有符号64-bit integer:-2^63 ~ 2^63 - 1
integer 有符号32-bit integer,-2^31 ~ 2^31 - 1
short 有符号16-bit integer,-32768 ~ 32767
byte 有符号8-bit integer,-128 ~ 127
double 64-bit IEEE 754 浮点数
float 32-bit IEEE 754 浮点数
half_float 16-bit IEEE 754 浮点数
boolean true,false
date https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html
binary 该类型的字段把值当做经过 base64 编码的字符串,默认不存储,且不可搜索

字符串类型

在 ES 7.x 有两种字符串类型:text 和 keyword,在 ES 5.x 之后 string 类型已经不再支持了。

text :类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字,text 类型会被 Lucene 分词器(Analyzer)处理为一个个词项,并使用 Lucene 倒排索引存储,text 字段不能被用于排序,如果需要使用该类型的字段只需要在定义映射时指定 JSON 中对应字段的 type 为 text。

keyword:不会被分词,适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过滤、排序、聚合检索,也可以用于精确查询。

各种查询:

# 查询所有
body = {
    "query":{
        "match_all":{}
    }
}

# 等于查询
# term查询:查询 preview 字段里有某个关键词的文档
# terms 查询:查询某个字段里有多个关键词的文档

# term: 查询 xx = “xx”
body = {
    "query":{
        "term":{
            "name":"python"
        }
    }
}

# terms: 查询 xx = “xx” 或 xx = “yy”
body = {
    "query":{
        "terms":{
            "name":[
                "ios","android"
            ]
        }
    }
}

# 包含查询
# match 查询可以接受文字,数字日期等数据类型
# match 和term的区别是,match 查询的时候,elasticsearch会根据你给定的字段提供合适的分析器,而term查询时不会有分析器分析的过程

# match: 匹配name包含"python"关键字的数据
body = {
    "query":{
        "match":{
            "name":"python"
        }
    }
}

# multi_match: 在name和addr里匹配包含深圳关键字的数据
body = {
    "query":{
        "multi_match":{
            "query":"深圳",
            "fields":["name", "addr"]
        }
    }
}

# 通过match_phrase查询
# 短语查询,slop定义的关键词之间隔多个未知的单词
# 查询elasticsearch,distributed 之间间隔2个单词的文档

{
	"query"{
	"match_phrase":{
		"preview":{
		"query":"Elasticsearch,distributed",
		"slop":2
		}
	}
}
    
# ids 查询id

# 搜索出id为1或2的所有数据
body = {
    "query":{
        "ids":{
            "type":"type_name",
            "values":[
                "1","2"
            ]
        }
    }
}

# 复合查询 bool 查询:bool有3类查询关系,must(都满足),should(其中一个满足),must_not(都不满足)

# 获取name="python"并且age=18的所有数据
body = {
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "name":"python"
                    }
                },
                {
                    "term":{
                        "age":18
                    }
                }
            ]
        }
    }
}

# 切片式查询

# 从第2条数据开始,获取4条数据,索引 从 0 开始
body = {
    "query":{
        "match_all":{}
    },
    "from":2,    # 从第二条数据开始
    "size":4,    # 获取4条数据
}

# 范围查询

# 查询18<=age<=30的所有数据
body = {
    "query":{
        "range":{
            "age":{
                "gte":18,       # >=18
                "lte":30        # <=30
            }
        }
    }
}

# 前缀查询

# 查询前缀为"赵"的所有数据
body = {
    "query":{
        "prefix":{
            "name":"p"
        }
    }
}

# 查询name以id为后缀的所有数据
body = {
    "query":{
        "wildcard":{
            "name":"*id"
        }
    }
}

# 排序

body = {
    "query":{
        "match_all":{}
    }
    "sort":{
        "age":{                 # 根据age字段升序排序
            "order":"asc"       # asc升序,desc降序
        }
    }
}

# 多字段排序,注意顺序!写在前面的优先排序
body = {
    "query":{
        "match_all":{}
    }
    "sort":[{
        "age":{                # 先根据age字段升序排序
            "order":"asc"      # asc升序,desc降序
        }
    },{
        "name":{               # 后根据name字段升序排序
            "order":"asc"      # asc升序,desc降序
        }
    }],
}

# filter_path, 响应过滤

# 只要 _id 数据
In [147]: es.search(index='wl_test',doc_type='data',filter_path=('hits.hits._id'))
d:\python36\lib\site-packages\elasticsearch\connection\base.py:209: ElasticsearchWarning: [types removal] Specifying types in search requests is deprecated.
  warnings.warn(message, category=ElasticsearchWarning)
Out[147]:
{'hits': {'hits': [{'_id': 'wVk5Rn0BM5UnHl8RH9ZL'},
   {'_id': 'wlk5Rn0BM5UnHl8RINYy'},
   {'_id': 'w1k5Rn0BM5UnHl8RINZK'},
   {'_id': 'xFk5Rn0BM5UnHl8RINZe'}]}}

# 多个条件用逗号隔开
In [149]: es.search(index='wl_test',doc_type='data',filter_path=('hits.hits._id','hits.hits._source'))
d:\python36\lib\site-packages\elasticsearch\connection\base.py:209: ElasticsearchWarning: [types removal] Specifying types in search requests is deprecated.
  warnings.warn(message, category=ElasticsearchWarning)
Out[149]:
{'hits': {'hits': [{'_id': 'wVk5Rn0BM5UnHl8RH9ZL',
    '_source': {'title': '美国留给伊拉克的是个烂摊子吗',
     'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
     'date': '2011-12-16'}},
   {'_id': 'wlk5Rn0BM5UnHl8RINYy',
    '_source': {'title': '公安部:各地校车将享最高路权',
     'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
     'date': '2011-12-16'}},
   {'_id': 'w1k5Rn0BM5UnHl8RINZK',
    '_source': {'title': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
     'url': 'https://news.qq.com/a/20111216/001044.htm',
     'date': '2011-12-17'}},
   {'_id': 'xFk5Rn0BM5UnHl8RINZe',
    '_source': {'title': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
     'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
     'date': '2011-12-18'}}]}}

# count 获取数量
In [150]: es.count(index='wl_test',doc_type='data')
Out[150]:
{'count': 4,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}}

# 度量类聚合

# 搜索所有数据,并获取age最小的值
body = {
    "query":{
        "match_all":{}
    },
    "aggs":{                        # 聚合查询
        "min_age":{                 # 最小值的key,随便指定
            "min":{                 # 最小
                "field":"age"       # 查询"age"的最小值
            }
        }
    }
}

# 搜索所有数据,并获取age最大的值
body = {
    "query":{
        "match_all":{}
    },
    "aggs":{                        # 聚合查询
        "max_age":{                 # 最大值的key
            "max":{                 # 最大
                "field":"age"       # 查询"age"的最大值
            }
        }
    }
}

# 搜索所有数据,并获取所有age的和,时间类型也可以
body = {
    "query":{
        "match_all":{}
    },
    "aggs":{                        # 聚合查询
        "sum_age":{                 # 和的key
            "sum":{                 # 和
                "field":"age"       # 获取所有age的和
            }
        }
    }
}

# 搜索所有数据,获取所有age的平均值
body = {
    "query":{
        "match_all":{}
    },
    "aggs":{                        # 聚合查询
        "avg_age":{                 # 平均值的key
            "avg":{                 # 平均值
                "field":"age"       # 获取所有age的平均值
            }
        }
    }
}

# from ,size
# from:从“第几条”开始查询
# size:查询多少条
body = {
    "query":{
        "match_all":{}
    },
    "size":"50",
    "from":"0"
}

bool 和 filtered

es 5.0版本更新后,filtered的查询将替换为bool查询。

filtered是比较老的的版本的语法。现在目前已经被bool替代。推荐使用bool。

must 与 filter

must, 返回的文档必须满足must子句的条件,并且参与计算分值
filter, 返回的文档必须满足filter子句的条件。但是跟Must不一样的是,不会计算分值, 并且可以使用缓存

从上面的描述来看,你应该已经知道,如果只看查询的结果,must和filter是一样的。区别是场景不一样。如果结果需要算分就使用must,否则可以考虑使用filter。

为了说明filter查询高效的原因,我们需要引入ES的一个概念 query context和 filter context。

query context

query context关注的是,文档到底有多匹配查询的条件,这个匹配的程度是由相关性分数决定的,分数越高自然就越匹配。所以这种查询除了关注文档是否满足查询条件,还需要额外的计算相关性分数.

filter context

filter context关注的是,文档是否匹配查询条件,结果只有两个,是和否。没有其它额外的计算。它常用的一个场景就是过滤时间范围。

并且filter context会自动被ES缓存结果,效率进一步提高。

对于bool查询,must使用的就是query context,而filter使用的就是filter context。

除了是否计算相关性算分的差别,经常使用的过滤器将被Elasticsearch自动缓存,以提高性能。

filter 查询

{
"query":{
        "bool":{
            "filter":[
                {"term":
                    {"price":40}
                }
            ]
        }
    }
}

filter的两种用法

1 嵌套在bool下

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "term":{"title":"kitchen3"}
        }
      },
      "filter": {
        "term": {
          "price":1000
        }
      }
    }
  }
}

2 在根目录下使用

{
  "query":{
    "term":{"title":"kitchen3"}
  },
  "filter":{
    "term":{"price":1000}
  }
}

位置:bool下

区别:在filter query先执行filter,不计算score,再执行query。

位置:根目录下

区别:根目录中的filter在query后执行。

备注:如果还要在搜索结果中执行aggregation操作,filter query聚合的是filter和query之后的结果,而filter聚合的是query的结果

script 获取值

search,用doc

update,用ctx

原文链接:https://blog.csdn.net/qq_36697880/article/details/100660867
原文链接:https://blog.csdn.net/cui_yonghua/article/details/107510609
原文链接:https://blog.csdn.net/weixin_39723544/article/details/103676958
原文链接:https://www.cnblogs.com/remainsu/p/python-cha-xun-elasticsearch-chang-yong-fang-fa-qu.html
原文链接:https://blog.csdn.net/pony_maggie/article/details/106062284
原文链接:https://blog.csdn.net/u013613428/article/details/78134170/
原文链接:https://blog.csdn.net/yyd19921214/article/details/54341248/
原文地址:https://www.cnblogs.com/pythonwl/p/15589639.html