当前位置:   article > 正文

django集成es(django-elasticsearch-dsl-drf)_django-elasticsearch-dsl详解

django-elasticsearch-dsl详解

前提介绍

在此版本下,es自动与mysql或其他数据库,进行数据同步(修改,删除.新增),update并不会自动同步

1. 准备模拟数据,安装json-server(不安装也可以.本文没有安装)

json-server的安装https://www.jianshu.com/p/920d73fc32de

  1. # 本文借鉴
  2. https://www.jianshu.com/p/920d73fc32de
  3. # 安装(windows上安装),以管理员身份打开cmd
  4. npm install -g json-server
  5. # 测试安装成功
  6. json-server -h
  7. # 在D盘新建一个文件夹JsonServer
  8. # 进入JsonServer文件夹,初始化
  9. npm init
  10. # 在JsonServer文件夹里面新建db.json,用于接口数据
  11. {
  12. "news": [
  13. {
  14. "id":1,
  15. "title":"Tesla's Autopilot, other driver assists are in a regulatory grey zone",
  16. "content":"Filed under: Government/Legal,Tesla,Safety,Technology Continue reading Tesla's Autopilot, other driver assists are in a regulatory grey zone Tesla's Autopilot, other driver assists are in a regulatory grey zone originally appeared on Autoblog on Sat, 24 Apr"
  17. },
  18. {
  19. "id":2,
  20. "title":"‘A Bunch of People Will Probably Die’ at Onset of Mars Colonisation, Musk Cautions",
  21. "content":"The Silicone Valley mogul has candidly outlined the pitfalls of potential trips to the red planet, as his brainchild SpaceX has been going to great lengths to make commercial tourism on Mars possible one day."
  22. },
  23. {
  24. "id":3,
  25. "title":"IRS says to do this one thing to get the biggest possible tax refund",
  26. "content":"In a normal year, one in which the country wasn't dealing with the catastrophic public health and financial impacts of a global pandemic, tax season would..."
  27. }
  28. ]
  29. }
  30. # 安装依赖模块,安装完成会发现多了两个文件:
  31. npm install json-server --save
  32. # 修改配置文件
  33. 打开package.json文件,将scripts进行修改,如下:
  34. "scripts": {
  35. "json:server": "json-server --watch db.json"
  36. },
  37. # 完成之后,输入命令,运行:
  38. npm run json:server
  39. # 访问
  40. http://localhost:3000/news

2.django集成es

需要环境(文章中有requirements,无需担心)

django-elasticsearch-dsl==7.2.0
django-elasticsearch-dsl-drf==0.22

  1. python3.6.8
  2. django==3.2
  3. djangorestframework==3.12.4
  4. elasticsearch-dsl==7.3.0
  5. django-elasticsearch-dsl==7.2.0
  6. django-elasticsearch-dsl-drf==0.22

环境安装

  1. # 创建一个虚拟环境
  2. # 安装Djangg3.2
  3. pip3 install django==3.2 -i https://pypi.douban.com/simple/
  4. # 创建一个app news
  5. # 安装依赖环境
  6. pip3 install -r requirements.txt -i https://pypi.douban.com/simple

requirements

  1. asgiref==3.3.4
  2. certifi==2020.12.5
  3. chardet==4.0.0
  4. Django==3.2
  5. django-cors-headers==3.7.0
  6. django-debug-toolbar==3.2.1
  7. django-discover-runner==1.0
  8. django-elasticsearch-dsl==7.2.0
  9. django-elasticsearch-dsl-drf==0.22
  10. django-froala-editor==3.2.2
  11. django-ipware==3.0.2
  12. django-nine==0.2.4
  13. django-redis==4.12.1
  14. django-rest-elasticsearch==0.4.2
  15. django-role-permissions==3.1.1
  16. django-webpack-loader==0.7.0
  17. djangorestframework==3.12.4
  18. elasticsearch==7.12.0
  19. elasticsearch-dsl==7.3.0
  20. Faker==8.1.0
  21. idna==2.10
  22. ipaddress==1.0.23
  23. Pillow==8.2.0
  24. python-dateutil==2.8.1
  25. pytz==2021.1
  26. redis==3.5.3
  27. requests==2.25.1
  28. six==1.15.0
  29. sqlparse==0.4.1
  30. text-unidecode==1.3
  31. typing-extensions==3.7.4.3
  32. urllib3==1.26.4

# settings.py进行配置

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. ...
  4. 'rest_framework',
  5. 'django_elasticsearch_dsl',
  6. 'django_elasticsearch_dsl_drf',
  7. ]
  8. ELASTICSEARCH_DSL = {
  9. 'default': {
  10. 'hosts': 'localhost:9200'
  11. },
  12. }

# 在 news app 下的 models.py:

  1. from django.db import models
  2. # Create your models here.
  3. class ElasticNews(models.Model):
  4. title = models.CharField(max_length=100)
  5. content = models.TextField()

# 在 news app 的 admin.py 中进行如下的修改

本文用法

  1. from django.contrib import admin
  2. # Register your models here.
  3. from news.models import *
  4. admin.site.register(ElasticNews)

admin的第二种用法 

    list_display = []  显示跟添加字段无关
    list_filter = []  
    search_fields = [] 
    readonly_fields = []
    filter_horizontal = []

  1. from django.contrib import admin
  2. from .models import *
  3. @admin.register(Book)
  4. class BookAdmin(admin.ModelAdmin):
  5. """Book admin."""
  6. list_display = ('title', 'price', 'publication_date')
  7. search_fields = ('title',)
  8. # 多选字段
  9. filter_horizontal = ('authors', 'tags',)
  10. @admin.register(Author)
  11. class AuthorAdmin(admin.ModelAdmin):
  12. """Author admin."""
  13. list_display = ('name', 'email',)
  14. search_fields = ('name',)
  15. @admin.register(Publisher)
  16. class PublisherAdmin(admin.ModelAdmin):
  17. """Publisher admin."""
  18. list_display = ('name',)
  19. search_fields = ('name',)
  20. @admin.register(Tag)
  21. class TagAdmin(admin.ModelAdmin):
  22. """Tag admin."""
  23. list_display = ('title',)
  24. search_fields = ('title',)

# news app 下创建一个叫做 documents.py 的文件:

  1. from django_elasticsearch_dsl import (
  2. Document,
  3. fields,
  4. Index,
  5. )
  6. from .models import ElasticNews
  7. # 创建索引
  8. PUBLISHER_INDEX = Index('elastic_news')
  9. # 索引配置
  10. PUBLISHER_INDEX.settings(
  11. number_of_shards=1,
  12. number_of_replicas=0
  13. )
  14. # 创建映射及字段类型
  15. @PUBLISHER_INDEX.doc_type
  16. class NewsDocument(Document):
  17. id = fields.IntegerField(attr='id')
  18. fielddata = True
  19. title = fields.TextField(
  20. fields={
  21. 'keyword': {
  22. 'type': 'keyword',
  23. }
  24. }
  25. )
  26. content = fields.TextField(
  27. fields={
  28. 'keyword': {
  29. 'type': 'keyword',
  30. }
  31. },
  32. )
  33. # 配置模型
  34. class Django(object):
  35. model = ElasticNews

# News app 下创建一个叫做 serializsers.py 的文件:

  1. import json
  2. from .models import ElasticNews
  3. from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
  4. from .documents import *
  5. from rest_framework import serializers
  6. # 创建序列化器
  7. class NewsDocumentSerializer(DocumentSerializer):
  8. # 同样支持重写字段
  9. title = serializers.SerializerMethodField()
  10. class Meta(object):
  11. """Meta options."""
  12. # 模型
  13. model = ElasticNews
  14. # 索引
  15. document = NewsDocument
  16. # 控制序列化的字段
  17. fields = ('id', 'title', 'content')
  18. # fields = '__all__'
  19. # 自定义返回数据
  20. def get_title(self, obj):
  21. # print('dddddddddddddd', obj.price)
  22. return obj.price

# 在 News app 下的 views.py 文件,以便能在访问页面时生产相应的 Elasticsearch 文档

  1. from django.http import JsonResponse
  2. import requests
  3. import json
  4. from news.models import *
  5. from .documents import *
  6. from .serializers import *
  7. from django_elasticsearch_dsl_drf.filter_backends import (
  8. FilteringFilterBackend,
  9. CompoundSearchFilterBackend
  10. )
  11. from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
  12. from django_elasticsearch_dsl_drf.filter_backends import (
  13. FilteringFilterBackend,
  14. OrderingFilterBackend,
  15. )
  16. # 写入es的函数
  17. def generate_random_data():
  18. # 安装JsonServer,
  19. """
  20. url = 'http://localhost:3000/news'
  21. r = requests.get(url)
  22. payload = json.loads(r.text)
  23. count = 1
  24. print("---------------------payload--------------", payload)
  25. print("type of payload is: ", type(payload))
  26. for data in payload:
  27. # print("title: ", data['title'])
  28. # print("content: ", data['content'])
  29. ElasticNews.objects.create(
  30. title=data['title'],
  31. content=data['content']
  32. )
  33. """
  34. # 不安装JsonServer,自己构建数据
  35. payload = [
  36. {'title': '洞c内', 'content': 'casac', 'price': '666'},
  37. {'title': '传s说', 'content': 'cas', 'price': '99'},
  38. {'title': '啊不错', 'content': 'casa', 'price': '966'}
  39. ]
  40. for data in payload:
  41. ElasticNews.objects.create(
  42. **data
  43. )
  44. # 写入es
  45. def index(request):
  46. # es与mysql自动同步数据
  47. generate_random_data()
  48. return JsonResponse({'status': 200})
  49. # return HttpResponse("Hello, the world")
  50. # 用来读数据进行搜索并排序的一个 view
  51. class PublisherDocumentView(DocumentViewSet):
  52. # mapping
  53. document = NewsDocument
  54. # 序列化器
  55. serializer_class = NewsDocumentSerializer
  56. lookup_field = 'id'
  57. fielddata = True
  58. filter_backends = [
  59. FilteringFilterBackend,
  60. OrderingFilterBackend,
  61. CompoundSearchFilterBackend,
  62. ]
  63. # 在全文中搜索范围的字段配置(模糊匹配)
  64. # Define filtering fields
  65. filter_fields = {
  66. 'title': 'title',
  67. 'content': 'content',
  68. # 'id': 'id',
  69. }
  70. # Define search fields
  71. search_fields = (
  72. # 'id',
  73. 'title',
  74. 'content',
  75. )
  76. # Define ordering fields
  77. ordering_fields = {
  78. 'id': None,
  79. }
  80. # 指定默认顺序
  81. ordering = ('id', 'content')
  82. # 支持多个参数
  83. multi_match_search_fields = (
  84. 'title',
  85. 'content',
  86. )
  87. # 测试
  88. def update_data(request):
  89. # 群更新会触发
  90. # query = ElasticNews.objects.all()
  91. # for item in query:
  92. # item.title = 'uuuuuuuuuuu'
  93. # item.save()
  94. # 单更新会触发
  95. # obj = ElasticNews.objects.filter(id=3).first()
  96. # obj.title = '刘亚萍99999999999'
  97. # obj.save()
  98. # create会触发
  99. # ElasticNews.objects.create(title='cas', content='222', price='85')
  100. # ElasticNews.objects.create(title='多对多', content='cas', price='85')
  101. ElasticNews.objects.create(title='cas', content='csa', price='85')
  102. # ElasticNews.objects.create(title='cas2', content='lcas', price='85')
  103. # 删除
  104. # ElasticNews.objects.filter(id=4).delete()
  105. # update不会触发es与mysql同步,也不会触发信号post_save
  106. # ElasticNews.objects.filter(id=1).update(title='圆梦去', content='222', price='85')
  107. return JsonResponse({'status': 200})

# 修改 ulrpatterns

  1. from django.contrib import admin
  2. from django.urls import path
  3. from news.views import *
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('search/', PublisherDocumentView.as_view({'get': 'list'})),
  7. path('add/', index),
  8. path('update/', update_data),
  9. ]

# 我们使用如下的命令来创建 Elasticsearch 索引 mapping:

  1. python manage.py makemigrations
  2. python manage.py migrate
  3. # 执行这一句,如果存在索引,就删除重新构建,不执行也可以,保证当前配置的索引唯一即可
  4. python manage.py search_index --rebuild

 # 访问 

  1. http://127.0.0.1:8000/
  2. http://127.0.0.1:8000/search/

查询使用 

  1. class Meta:
  2. """Meta options."""
  3. # 即模型对象返回的记录结果集是按照这个字段排序的。
  4. ordering = ["id"]
  5. # 使用过滤排序
  6. # 所有字段中搜索cas
  7. http://127.0.0.1:8000/search/?search=cas
  8. # 要在特定字段 中搜索术“cas”
  9. # 例子:要在字段title中搜索“cas”
  10. http://127.0.0.1:8000/search/?search=title:cas
  11. # 搜索多个术语 二者或的关系
  12. http://127.0.0.1:8000/search/?search=cas&search=洞c内
  13. # 要在特定字段 搜索多个术语 二者或的关系
  14. http://127.0.0.1:8000/search/?search=title:cas&search=content:卡车
  15. # 按单个字段筛选文档
  16. http://127.0.0.1:8000/search/?title=cas
  17. # 或搜索(不支持中文)
  18. http://127.0.0.1:8000/search/?title__in=cas__cas2
  19. # and(不支持中文)
  20. http://127.0.0.1:8000/search/?title=cas&content=csa
  21. # 按单个字段的单词部分筛选文档(正则搜索)
  22. http://127.0.0.1:8000/search/?title__wildcard=*内
  23. # 按字段对文档进行排序(升序
  24. http://127.0.0.1:8000/search/?search=content:cas&ordering=id
  25. # 按字段对文档进行排序(降序)
  26. http://127.0.0.1:8000/search/?search=content:cas&ordering=-id
  27. # 按多个字段对文档进行排序
  28. 如果要按多个字段排序,请使用多个排序查询参数。在下面的示例中,文档将首先按字段排序(降序),然后按字段排序(升序)
  29. http://127.0.0.1:8080/search/publisher/?ordering=-country&ordering=city

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/205581
推荐阅读
相关标签
  

闽ICP备14008679号