使用 python 在 elasticsearch-dsl 中聚合一个字段
aggregate a field in elasticsearch-dsl using python
谁能告诉我如何编写 Python 语句来汇总(求和和计数)有关我的文档的内容?
脚本
from datetime import datetime
from elasticsearch_dsl import DocType, String, Date, Integer
from elasticsearch_dsl.connections import connections
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="attendance")
s = s.execute()
for tag in s.aggregations.per_tag.buckets:
print (tag.key)
输出
File "/Library/Python/2.7/site-packages/elasticsearch_dsl/utils.py", line 106, in __getattr__
'%r object has no attribute %r' % (self.__class__.__name__, attr_name))
AttributeError: 'Response' object has no attribute 'aggregations'
这是什么原因造成的? "aggregations"关键字错了吗?我需要导入其他包吗?如果 "attendance" 索引中的文档有一个名为 emailAddress 的字段,我将如何计算哪些文档具有该字段的值?
首先。我现在注意到我在这里写的实际上没有定义聚合。关于如何使用它的文档对我来说不是很易读。使用我上面写的,我会扩展。我正在更改索引名称以提供更好的示例。
from datetime import datetime
from elasticsearch_dsl import DocType, String, Date, Integer
from elasticsearch_dsl.connections import connections
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="airbnb", doc_type="sleep_overs")
s = s.execute()
# invalid! You haven't defined an aggregation.
#for tag in s.aggregations.per_tag.buckets:
# print (tag.key)
# Lets make an aggregation
# 'by_house' is a name you choose, 'terms' is a keyword for the type of aggregator
# 'field' is also a keyword, and 'house_number' is a field in our ES index
s.aggs.bucket('by_house', 'terms', field='house_number', size=0)
上面我们为每个门牌号创建了 1 个桶。因此,桶的名称将是门牌号。 ElasticSearch (ES) 将始终给出适合该存储桶的文档的文档计数。 Size=0 表示使用所有结果,因为 ES 的默认设置为 return 仅 10 个结果(或您的开发人员设置的任何结果)。
# This runs the query.
s = s.execute()
# let's see what's in our results
print s.aggregations.by_house.doc_count
print s.hits.total
print s.aggregations.by_house.buckets
for item in s.aggregations.by_house.buckets:
print item.doc_count
我之前的错误是认为 Elastic Search 查询默认具有聚合。您可以自己定义它们,然后执行它们。然后您的回复可以拆分为您提到的聚合器。
上面的 CURL 应该是这样的:
注意:我使用 SENSE 和 ElasticSearch plugin/extension/add-on for Google Chrome。在 SENSE 中,您可以使用 // 来注释掉内容。
POST /airbnb/sleep_overs/_search
{
// the size 0 here actually means to not return any hits, just the aggregation part of the result
"size": 0,
"aggs": {
"by_house": {
"terms": {
// the size 0 here means to return all results, not just the the default 10 results
"field": "house_number",
"size": 0
}
}
}
}
解决方法。 DSL GIT 上有人告诉我别翻译了,就用这个方法吧。它更简单,你可以用 CURL 编写困难的东西。这就是为什么我称之为解决方法。
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="airbnb", doc_type="sleep_overs")
# how simple we just past CURL code here
body = {
"size": 0,
"aggs": {
"by_house": {
"terms": {
"field": "house_number",
"size": 0
}
}
}
}
s = Search.from_dict(body)
s = s.index("airbnb")
s = s.doc_type("sleepovers")
body = s.to_dict()
t = s.execute()
for item in t.aggregations.by_house.buckets:
# item.key will the house number
print item.key, item.doc_count
希望这对您有所帮助。我现在在 CURL 中设计所有内容,然后使用 Python 语句剥离结果以获得我想要的。这有助于具有多个级别的聚合(子聚合)。
我还没有代表发表评论,但我想对 Matthew 对 VISQL 关于 from_dict 的回答的评论做一个小小的修正。如果要维护搜索属性,请使用 update_from_dict 而不是 from_dict.
根据 Docs ,from_dict 创建一个新的搜索对象,但 update_from_dict 将在适当的位置进行修改,如果搜索已经具有索引等属性,这就是您想要的,使用等
因此您可能希望在搜索之前声明查询主体,然后像这样创建搜索:
query_body = {
"size": 0,
"aggs": {
"by_house": {
"terms": {
"field": "house_number",
"size": 0
}
}
}
}
s = Search(using=client, index="airbnb", doc_type="sleep_overs").update_from_dict(query_body)
谁能告诉我如何编写 Python 语句来汇总(求和和计数)有关我的文档的内容?
脚本
from datetime import datetime
from elasticsearch_dsl import DocType, String, Date, Integer
from elasticsearch_dsl.connections import connections
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="attendance")
s = s.execute()
for tag in s.aggregations.per_tag.buckets:
print (tag.key)
输出
File "/Library/Python/2.7/site-packages/elasticsearch_dsl/utils.py", line 106, in __getattr__
'%r object has no attribute %r' % (self.__class__.__name__, attr_name))
AttributeError: 'Response' object has no attribute 'aggregations'
这是什么原因造成的? "aggregations"关键字错了吗?我需要导入其他包吗?如果 "attendance" 索引中的文档有一个名为 emailAddress 的字段,我将如何计算哪些文档具有该字段的值?
首先。我现在注意到我在这里写的实际上没有定义聚合。关于如何使用它的文档对我来说不是很易读。使用我上面写的,我会扩展。我正在更改索引名称以提供更好的示例。
from datetime import datetime
from elasticsearch_dsl import DocType, String, Date, Integer
from elasticsearch_dsl.connections import connections
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="airbnb", doc_type="sleep_overs")
s = s.execute()
# invalid! You haven't defined an aggregation.
#for tag in s.aggregations.per_tag.buckets:
# print (tag.key)
# Lets make an aggregation
# 'by_house' is a name you choose, 'terms' is a keyword for the type of aggregator
# 'field' is also a keyword, and 'house_number' is a field in our ES index
s.aggs.bucket('by_house', 'terms', field='house_number', size=0)
上面我们为每个门牌号创建了 1 个桶。因此,桶的名称将是门牌号。 ElasticSearch (ES) 将始终给出适合该存储桶的文档的文档计数。 Size=0 表示使用所有结果,因为 ES 的默认设置为 return 仅 10 个结果(或您的开发人员设置的任何结果)。
# This runs the query.
s = s.execute()
# let's see what's in our results
print s.aggregations.by_house.doc_count
print s.hits.total
print s.aggregations.by_house.buckets
for item in s.aggregations.by_house.buckets:
print item.doc_count
我之前的错误是认为 Elastic Search 查询默认具有聚合。您可以自己定义它们,然后执行它们。然后您的回复可以拆分为您提到的聚合器。
上面的 CURL 应该是这样的:
注意:我使用 SENSE 和 ElasticSearch plugin/extension/add-on for Google Chrome。在 SENSE 中,您可以使用 // 来注释掉内容。
POST /airbnb/sleep_overs/_search
{
// the size 0 here actually means to not return any hits, just the aggregation part of the result
"size": 0,
"aggs": {
"by_house": {
"terms": {
// the size 0 here means to return all results, not just the the default 10 results
"field": "house_number",
"size": 0
}
}
}
}
解决方法。 DSL GIT 上有人告诉我别翻译了,就用这个方法吧。它更简单,你可以用 CURL 编写困难的东西。这就是为什么我称之为解决方法。
# Define a default Elasticsearch client
client = connections.create_connection(hosts=['http://blahblahblah:9200'])
s = Search(using=client, index="airbnb", doc_type="sleep_overs")
# how simple we just past CURL code here
body = {
"size": 0,
"aggs": {
"by_house": {
"terms": {
"field": "house_number",
"size": 0
}
}
}
}
s = Search.from_dict(body)
s = s.index("airbnb")
s = s.doc_type("sleepovers")
body = s.to_dict()
t = s.execute()
for item in t.aggregations.by_house.buckets:
# item.key will the house number
print item.key, item.doc_count
希望这对您有所帮助。我现在在 CURL 中设计所有内容,然后使用 Python 语句剥离结果以获得我想要的。这有助于具有多个级别的聚合(子聚合)。
我还没有代表发表评论,但我想对 Matthew 对 VISQL 关于 from_dict 的回答的评论做一个小小的修正。如果要维护搜索属性,请使用 update_from_dict 而不是 from_dict.
根据 Docs ,from_dict 创建一个新的搜索对象,但 update_from_dict 将在适当的位置进行修改,如果搜索已经具有索引等属性,这就是您想要的,使用等
因此您可能希望在搜索之前声明查询主体,然后像这样创建搜索:
query_body = {
"size": 0,
"aggs": {
"by_house": {
"terms": {
"field": "house_number",
"size": 0
}
}
}
}
s = Search(using=client, index="airbnb", doc_type="sleep_overs").update_from_dict(query_body)