在用python的两个库:Elasticsearch,elasticsearch_dsl操作elastic时。二次封装了Elasticsearch库中的一些方法以方便业务场景:
from elasticsearch7 import Elasticsearch
from elasticsearch_dsl import Search
from config.config import conf
HOST = conf["Elasticsearch"]["host"]
PORT = conf["Elasticsearch"]["port"]
TIMEOUT = conf["Elasticsearch"]["timeout"]
class EsOperate(Elasticsearch):
def __init__(self, **kwargs):
super(EsOperate, self).__init__(**kwargs)
self.es = Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)
def creat_one_data(self, index, body, **kwargs):
""" 新增单条数据 """
return self.es.index(index=index, body=body, **kwargs)
def delete_one_data(self, index, id, **kwargs):
""" 通过id删除单条数据 """
return self.es.delete(index=index, id=id, **kwargs)
def delete_by_query(self, index, body, **kwargs):
""" 条件删除数据 """
return self.es.delete_by_query(index=index, body=body, **kwargs)
def update(self, index, id, body, **kwargs):
""" 通过id更新单条数据(支持部分更新字段) """
return self.es.update(index=index, id=id, body={"doc": body}, **kwargs)
通过这样类的继承和重写能实现类的扩展,同时保留类原来的属性和方法,没有问题。同样 elasticsearch_dsl 库的 Search 类也很强大,Search 使用需要指定es连接:
es = EsOperate()
s = Search(using=es, index='xxxx')
通过实例化EsOperate对象,Search连接es失败:
定位原因
打印对象实例结果:
es1和es2:
def __init__(self, **kwargs):
super(EsOperate, self).__init__()
self.es = Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)
es1:
super(EsOperate, self).__init__()
self.es = Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)
es2:
Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)
可以看到,造成es1没有实例化成功是因为在继承时连接对象时从父类去找的,并没有将self.es = Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)作为es初始化连接对象返回
解决方法
明白原因,解决很简单,在继承父类==init==初始化方法时,传入连接参数即可:
def __init__(self, **kwargs):
super(EsOperate, self).__init__(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)
self.es = Elasticsearch(hosts=HOST, port=PORT, timeout=TIMEOUT, **kwargs)