在Django项目中使用Elasticsearch

发表于2019-11-11,长度2963, 201个单词, 8分钟读完
Flag Counter

在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’]拿到命中记录即可。

Written on November 11, 2019
分类: dev, 标签: python elasticsearch
如果你喜欢,请赞赏! davelet