在Django项目中使用Elasticsearch
在Django项目中使用elasticsearch同Java中有一点差别。Java的es库已经被大厂封装好了,直接调用对应的API就行(当前Java操作ES的API也特别复杂);而Python操作ES的方式主要是通过http发送json参数。不过这样和ES的入门方式一致,ES的各种文档也都是基于json格式请求的。
java的API也支持直接发送json参数
要使用elasticsearch,先要安装依赖:
pip install django-rest-elasticsearch
在Django 框架对数据库的操作一文中讲了Django是如何继承数据库的。要集成elasticsearch,可以基于数据库的模型(当然你可以说这个模型就是给elasticsearch用的,和数据库无关),因为很少单独使用elasticsearch,一般都是做为数据库的分压源存在的。不过也完全可以单独使用elasticsearch的模型,叫索引。类似于models.py,我们可以创建index.py用于存放ES的索引模型。
以前文中的数据库模型为例:
class MyMd(models.Model):
id = models.IntegerField
shop_id = models.CharField(max_length=8, default='')
goods_id = models.CharField(max_length=30, default='')
file = models.FileField(max_length=200, blank=False, null=False)
created_at = models.DateTimeField('创建时间', auto_now_add=True, null=False, blank=False)
created_by = models.CharField(max_length=50, default='')
updated_at = models.DateTimeField('变更时间', auto_now=True, null=False, blank=False)
updated_by = models.CharField(max_length=50, default='')
last_updated_at = models.DateTimeField('时间戳', auto_now=True)
def __str__(self):
return self.image_name + self.file.name
class Meta:
db_table = "my_table"
indexes = [
models.Index(fields=['shop_id', 'goods_id'])
]
我们在index.py中记录索引结构:
from elasticsearch_dsl import Integer, Text, Keyword, Float, Date, Document
class MyIndex(Document):
id = Integer()
shop_id = Text(fields={'keyword': Keyword()})
goods_id = Text(fields={'keyword': Keyword()})
goods_name = Text()
weight = Float()
created_at = Date()
created_by = Text()
class Index:
name = 'my_index'
类似于MyMd继承了Model,MyIndex继承了Document。里面也有一个内部类Index,用于指定索引的名称。
数据库的模型需要有序列化器,elasticsearch也是需要的。下面是上面的索引的序列化器:
class MyIndexSerializer(es_serializer.ElasticModelSerializer):
class Meta:
model = MyMd
es_model = MyIndex
fields = '__all__'
fields用于指定索引中的字段,__all__表示全部字段。
创建文档的时候,将数据库模型或者ES模传入MyIndexSerializer的构造器即可:
from elasticsearch_dsl.connections import connections
connections.create_connection(hosts='10.19.50.193:9200,10.19.65.68:9200,10.19.91.155:9200')
m = MyMd()
e = MyIndexSerializer(m)
e.save()
连接地址可以传入单个串或者是元组表示集群,调用序列化器ElasticModelSerializer的save方法即可保存,如果索引不存在会先创建。
如果要查询,创建客户端:
es_client = Elasticsearch('10.19.50.193:9200,10.19.65.68:9200,10.19.91.155:9200')
res = es_client.search(index='my_index',
body={
"query": {
"bool": {
"must": {
"match": {
"shop_id.keyword": "123456"
}
},
}
},
"from": 0,
"size": 1000
})
返回的数据格式都是一样的,使用res[‘hits’][‘hits’]拿到命中记录即可。
