Elasticserch与Elasticsearch_dsl用法

Elasticserch与Elasticsearch_dsl用法

Elasticsearch_dsl::https://elasticsearch-dsl.readthedocs.io/en/latest/search_dsl.html

Elasticserch:https://elasticsearch-py.readthedocs.io/en/master/api.html

1. 连接

from elasticsearch import Elasticsearch
es = Elasticsearch(hosts="127.0.0.1:9200")

# connections可以设置多个集群
from elasticsearch_dsl import connections
es = connections.create_connection(hosts=['localhost:9200'], timeout=60)

2. 查询

from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search

client = Elasticsearch()
s = Search(using=client)

API是可链接的,允许在一个语句中组合多个方法调用:

s = Search().using(client).query("match", title="python")

要将请求发送到Elasticsearch:

response = s.params(size=10000).execute()
# params(size) 为指定搜索结果返回条数,默认size是10,最大size为10000

如果只想迭代搜索返回的命中,可以遍历该Search对象:

for hit in s:
    print(hit.title)

搜索结果将被缓存。后续调用execute或尝试迭代已执行的Search对象不会触发发送到Elasticsearch的其他请求。强制请求指定 ignore_cache=True何时调用execute
出于调试目的,可以将Search对象序列化为dict 显式:

s = Search().using(client).query("match", title="python")
print(s.to_dict())

可以通过调用对象来删除与搜索匹配的文档deleteSearch而不是 execute像这样:

s = Search(index='i').query("match", title="python")
response = s.delete()

2.1 常用参数

1. 查询所有数据用match_all
es.search(index="my_index",doc_type="test_type")
 
# 或者
body = {
    "query":{
        "match_all":{}
    }
}

2. term 和 terms
# term: 查询name="python"的所有数据
body = {
    "query":{
        "term":{
            "name":"python"
        }
    }
}

# terms: 搜索出name="python"或name="android"的所有数据
body = {
    "query":{
        "terms":{
            "name":[
                "python","android"
            ]
        }
    }
}

3.match, multi_match
# match: 匹配name包含python关键字的数据,查询name包含python关键字的数据
body = {
    "query":{
        "match":{
            "name":"python"
        }
    }
}

# multi_match:在name和addr里匹配包含深圳关键字的数据
body = {
    "query":{
        "multi_match":{
            "query":"深圳",
            "fields":["name","addr"]
        }
    }
}
4.复合查询bool
bool3类查询关系,must(都满足),should(其中一个满足),must_not(都不满足)
# 获取name="python"并且age=18的所有数据
body = {
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "name":"python"
                    }
                },
                {
                    "term":{
                        "age":18
                    }
                }
            ]
        }
    }
}

5.切片式查询
# 从第2条数据开始,获取4条数据
body = {
    "query":{
        "match_all":{}
    }
    "from":2    # 从第二条数据开始
    "size":4    # 获取4条数据
}

6.范围查询
# 查询18<=age<=20的所有数据
body = {
    "query":{
        "range":{
            "age":{
                "gte":18,       # >=18
                "lte":20        # <=20
            }
        }
    }
}

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

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

9.排序
body = {
    "query":{
        "match_all":{}
    }
    "sort":{
        "age":{                 # 根据age字段升序排序
            "order":"asc"       # asc升序,desc降序
        }
    }
}
10.count
执行查询并获取该查询的匹配数
es.count(index="my_index",doc_type="test_type")

11.最大值,最小值,和,平均值

# 搜索所有数据,并获取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
            "sum":{                 # 平均值
                "field":"age"       # 获取所有age的平均值
            }
        }
    }
}

es.search(index="my_index",doc_type="test_type",body=body)

2.2 Q

from elasticsearch_dsl import Q

Q("multi_match", query='python django', fields=['title', 'body'])
Q({"multi_match": {"query": "python django", "fields": ["title", "body"]}})
q = Q("bool",must=[Q("range", start_time={"gte": start_time}), Q("range", end_time={"lte": end_time})])
s = Search(using=es, index=index, doc_type="test_tpye").query(q)

要将查询添加到Search对象,使用.query()方法:

q = Q("multi_match", query='python django', fields=['title', 'body'])
s = Search().query(q)

该方法还接受所有参数作为Q快捷方式:

s = s.query("multi_match", query='python django', fields=['title', 'body'])

如果已有查询对象或dict表示查询对象,则可以覆盖Search对象中使用的查询:

s.query = Q('bool', must=[Q('match', title='python'), Q('match', body='best')])

2.3 虚线字段

有时想要引用另一个字段中的字段,可以是多字段(title.keyword),也可以是结构化json文档address.city。为了更方便的Q快捷方式(还有 queryfilter以及exclude对方法Search的类),可以使用__(双下划线)代替关键字参数点的:

s = Search()
s = s.filter('term', category__keyword='Python')
s = s.query('match', address__city='prague')

或者:

s = Search()
s = s.filter('term', **{'category.keyword': 'Python'})
s = s.query('match', **{'address.city': 'prague'})

2.4 查询组合

可以使用逻辑运算符组合查询对象:

Q("match", title='python') | Q("match", title='django')
# {"bool": {"should": [...]}}

Q("match", title='python') & Q("match", title='django')
# {"bool": {"must": [...]}}

~Q("match", title="python")
# {"bool": {"must_not": [...]}}

.query()多次调用该方法时,&将在内部使用该运算符:

s = s.query().query()
print(s.to_dict())
# {"query": {"bool": {...}}}

如果要对查询表单进行精确控制,使用Q快捷方式直接构造组合查询:

q = Q('bool',
    must=[Q('match', title='python')],
    should=[Q(...), Q(...)],
    minimum_should_match=1
)
s = Search().query(q)

# start_time为开始时间,end_time为结束时间
q = Q('bool', must=[Q('range', start_time={"gte": start_time}), Q('range', end_time={"lte": end_time})])
s = Search().query(q)

2.5 过滤器

如果要在Search之后添加查询, 可以使用该filter()方法使事情变得更容易:

s = Search()
s = s.filter('terms', tags=['search', 'python'])


过滤,在此为范围过滤,range是方法,timestamp是所要查询的field的名字,gte意为大于等于,lt意为小于,根据需要设定即可(似乎过滤只能接受数字形式的内容,如果是文本就会返回空)
关于term和match的区别,term是精确匹配,match会模糊化,会进行分词,返回匹配度分数,(term查询字符串之接受小写字母,如果有大写会返回空即没有命中,match则是不区分大小写都可以进行查询,返回结果也一样)

例1:范围查询
s = s.filter("range", timestamp={"gte": 0, "lt": time.time()}).query("match", country="in")2:普通过滤
res_3 = s.filter("terms", balance_num=["39225", "5686"]).execute()

在幕后,这将生成一个Bool查询并将指定的 terms查询放入其filter分支,使其等效于:

s = Search()
s = s.query('bool', filter=[Q('terms', tags=['search', 'python'])])

如果要将post_filter元素用于分面导航,请使用该 .post_filter()方法。

exclude()可以查询查询中的项目,如下所示:

s = Search()
s = s.exclude('terms', tags=['search', 'python'])

这是简写: s = s.query('bool', filter=[~Q('terms', tags=['search', 'python'])])

2.6 聚合

聚合可以放在查询,过滤等操作的后面叠加,需要加aggs

要定义聚合,可以使用A快捷方式:

from elasticsearch_dsl import A

A('terms', field='tags')
# {"terms": {"field": "tags"}}

也可以使用.bucket().metric().pipeline()方法

bucket即为分组,其中第一个参数是分组的名字,自己指定即可,第二个参数是方法,第三个是指定的field。

metric也是同样,metric的方法有sum、avg、max、min等等,但是需要指出的是有两个方法可以一次性返回这些值,stats和extended_stats,后者还可以返回方差等值。

a = A('terms', field='category')
# {'terms': {'field': 'category'}}

a.metric('clicks_per_category', 'sum', field='clicks').bucket('tags_per_category', 'terms', field='tags')
# {
#   'terms': {'field': 'category'},
#   'aggs': {
#     'clicks_per_category': {'sum': {'field': 'clicks'}},
#     'tags_per_category': {'terms': {'field': 'tags'}}
#   }
# }


# 例1
s.aggs.bucket("per_country", "terms", field="timestamp").metric("sum_click", "stats", field="click").metric("sum_request", "stats", field="request")

# 例2
s.aggs.bucket("per_age", "terms", field="click.keyword").metric("sum_click", "stats", field="click")

# 例3
s.aggs.metric("sum_age", "extended_stats", field="age")

# 例4
s.aggs.bucket("per_age", "terms", field="country.keyword")
# 最后依然是要execute,此处注意s.aggs的操作不能用变量接收(如res=s.aggs的操作就是错误的),聚合的结果会在res中显示

# 例5
a = A("range", field="account_number", ranges=[{"to": 10}, {"from": 11, "to": 21}])

res = s.execute()

要向Search对象添加聚合,请使用.aggs属性作为顶级聚合:

s = Search()
a = A('terms', field='category')
s.aggs.bucket('category_terms', a)
# {
#   'aggs': {
#     'category_terms': {
#       'terms': {
#         'field': 'category'
#       }
#     }
#   }
# }

要么

s = Search()
s.aggs.bucket('articles_per_day', 'date_histogram', field='publish_date', interval='day')\
    .metric('clicks_per_day', 'sum', field='clicks')\
    .pipeline('moving_click_average', 'moving_avg', buckets_path='clicks_per_day')\
    .bucket('tags_per_day', 'terms', field='tags')

s.to_dict()
# {
#   "aggs": {
#     "articles_per_day": {
#       "date_histogram": { "interval": "day", "field": "publish_date" },
#       "aggs": {
#         "clicks_per_day": { "sum": { "field": "clicks" } },
#         "moving_click_average": { "moving_avg": { "buckets_path": "clicks_per_day" } },
#         "tags_per_day": { "terms": { "field": "tags" } }
#       }
#     }
#   }
# }

您可以按名称访问现有的key(类似字典的方式):

s = Search()
s.aggs.bucket('per_category', 'terms', field='category')
s.aggs['per_category'].metric('clicks_per_category', 'sum', field='clicks')
s.aggs['per_category'].bucket('tags_per_category', 'terms', field='tags')
response = s.params(size=10000).execute()

3.删除

es.delete(index='xxx', doc_type='xxx', id='xxx')

4.更新

body = {'doc': {}}
body['doc']['filed_name'] = '新的值'
es.update(index=_index, doc_type='alarm', id='xxx', body=body)
es.update(index='xxx', doc_type='xxx', id='xxx', body={待更新字段})
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用elasticsearch_dsl的示例代码: ```python # 引入必要的包 from elasticsearch_dsl import connections, Search from elasticsearch import Elasticsearch # 连接到elasticsearch es = connections.create_connection(hosts=["127.0.0.1:9200"], timeout=20) # 查询操作 search = Search(using=es, index="account_info") response = search.query("match", firstname="John").execute() for hit in response: print(hit.firstname, hit.lastname) # 更新文档 doc = search.get(id="1") doc.balance += 100 doc.save() # 删除文档 search.delete(id="2") # 关闭连接 es.close() ``` 以上示例代码展示了elasticsearch_dsl的基本用法。首先我们连接到elasticsearch实例,然后可以执行查询、更新和删除操作。在查询操作中,我们使用`Search`对象来构建查询条件,并执行`execute()`方法获取查询结果。在更新操作中,我们通过获取文档对象并修改其属性值,然后调用`save()`方法保存修改。在删除操作中,我们使用`delete()`方法指定要删除的文档id。最后,我们关闭连接。 请注意,以上示例中的索引名为"account_info",如果你使用的是不同的索引,请将其替换为你的索引名。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python中elasticsearch_dsl模块用法详解](https://blog.csdn.net/m0_72557783/article/details/126957624)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值