前提介绍

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

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

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

# 本文借鉴
https://www.jianshu.com/p/920d73fc32de
# 安装(windows上安装),以管理员身份打开cmd
npm  install  -g  json-server
# 测试安装成功
json-server -h
# 在D盘新建一个文件夹JsonServer
# 进入JsonServer文件夹,初始化
npm init
# 在JsonServer文件夹里面新建db.json,用于接口数据
{
  "news": [
    {
       "id":1,
       "title":"Tesla's Autopilot, other driver assists are in a regulatory grey zone",
       "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"
    },
    {
       "id":2,
       "title":"‘A Bunch of People Will Probably Die’ at Onset of Mars Colonisation, Musk Cautions",
       "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."
    },
    {
       "id":3,
       "title":"IRS says to do this one thing to get the biggest possible tax refund",
       "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..."
    }
  ]
}
# 安装依赖模块,安装完成会发现多了两个文件:
npm install json-server --save
# 修改配置文件
打开package.json文件,将scripts进行修改,如下:
    "scripts": {
    "json:server": "json-server --watch db.json"
},
# 完成之后,输入命令,运行:
npm run json:server
# 访问 
http://localhost:3000/news

2.django集成es

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

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

python3.6.8
django==3.2
djangorestframework==3.12.4
elasticsearch-dsl==7.3.0
django-elasticsearch-dsl==7.2.0
django-elasticsearch-dsl-drf==0.22

环境安装

# 创建一个虚拟环境

# 安装Djangg3.2
pip3 install django==3.2 -i https://pypi.douban.com/simple/
    
# 创建一个app news

# 安装依赖环境
pip3 install -r requirements.txt -i https://pypi.douban.com/simple

requirements

asgiref==3.3.4
certifi==2020.12.5
chardet==4.0.0
Django==3.2
django-cors-headers==3.7.0
django-debug-toolbar==3.2.1
django-discover-runner==1.0
django-elasticsearch-dsl==7.2.0
django-elasticsearch-dsl-drf==0.22
django-froala-editor==3.2.2
django-ipware==3.0.2
django-nine==0.2.4
django-redis==4.12.1
django-rest-elasticsearch==0.4.2
django-role-permissions==3.1.1
django-webpack-loader==0.7.0
djangorestframework==3.12.4
elasticsearch==7.12.0
elasticsearch-dsl==7.3.0
Faker==8.1.0
idna==2.10
ipaddress==1.0.23
Pillow==8.2.0
python-dateutil==2.8.1
pytz==2021.1
redis==3.5.3
requests==2.25.1
six==1.15.0
sqlparse==0.4.1
text-unidecode==1.3
typing-extensions==3.7.4.3
urllib3==1.26.4

# settings.py进行配置

INSTALLED_APPS = [
    'django.contrib.admin',
    ...
    'rest_framework',
    'django_elasticsearch_dsl',
    'django_elasticsearch_dsl_drf',    
]

ELASTICSEARCH_DSL = {
    'default': {
        'hosts': 'localhost:9200'
    },
}

# 在 news app 下的 models.py:

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

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

本文用法

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

admin的第二种用法 

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

from django.contrib import admin

from .models import *


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    """Book admin."""

    list_display = ('title', 'price', 'publication_date')
    search_fields = ('title',)
    # 多选字段
    filter_horizontal = ('authors', 'tags',)


@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    """Author admin."""

    list_display = ('name', 'email',)
    search_fields = ('name',)


@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    """Publisher admin."""

    list_display = ('name',)
    search_fields = ('name',)


@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    """Tag admin."""

    list_display = ('title',)
    search_fields = ('title',)

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

from django_elasticsearch_dsl import (
    Document,
    fields,
    Index,
)

from .models import ElasticNews

# 创建索引
PUBLISHER_INDEX = Index('elastic_news')

# 索引配置
PUBLISHER_INDEX.settings(
    number_of_shards=1,
    number_of_replicas=0
)


# 创建映射及字段类型
@PUBLISHER_INDEX.doc_type
class NewsDocument(Document):
    id = fields.IntegerField(attr='id')
    fielddata = True
    title = fields.TextField(
        fields={
            'keyword': {
                'type': 'keyword',
            }

        }
    )
    content = fields.TextField(
        fields={
            'keyword': {
                'type': 'keyword',

            }
        },
    )

    # 配置模型
    class Django(object):
        model = ElasticNews

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

import json
from .models import ElasticNews

from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
from .documents import *
from rest_framework import serializers


# 创建序列化器
class NewsDocumentSerializer(DocumentSerializer):
    # 同样支持重写字段
    title = serializers.SerializerMethodField()

    class Meta(object):
        """Meta options."""
        # 模型
        model = ElasticNews
        # 索引
        document = NewsDocument
        # 控制序列化的字段
        fields = ('id', 'title', 'content')
        # fields = '__all__'

    # 自定义返回数据
    def get_title(self, obj):
        # print('dddddddddddddd', obj.price)
        return obj.price

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

from django.http import JsonResponse
import requests
import json
from news.models import *

from .documents import *
from .serializers import *

from django_elasticsearch_dsl_drf.filter_backends import (
    FilteringFilterBackend,
    CompoundSearchFilterBackend
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from django_elasticsearch_dsl_drf.filter_backends import (
    FilteringFilterBackend,
    OrderingFilterBackend,
)


# 写入es的函数
def generate_random_data():
    # 安装JsonServer,
    """
    url = 'http://localhost:3000/news'
    r = requests.get(url)
    payload = json.loads(r.text)
    count = 1

    print("---------------------payload--------------", payload)

    print("type of payload is: ", type(payload))
    for data in payload:
        # print("title: ", data['title'])
        # print("content: ", data['content'])
        ElasticNews.objects.create(
            title=data['title'],
            content=data['content']
        )
    """
    # 不安装JsonServer,自己构建数据
    payload = [
        {'title': '洞c内', 'content': 'casac', 'price': '666'},
        {'title': '传s说', 'content': 'cas', 'price': '99'},
        {'title': '啊不错', 'content': 'casa', 'price': '966'}
    ]
    for data in payload:
        ElasticNews.objects.create(
            **data
        )


# 写入es
def index(request):
    # es与mysql自动同步数据
    generate_random_data()
    return JsonResponse({'status': 200})
    # return HttpResponse("Hello, the world")


# 用来读数据进行搜索并排序的一个 view
class PublisherDocumentView(DocumentViewSet):
    # mapping
    document = NewsDocument
    # 序列化器
    serializer_class = NewsDocumentSerializer
    lookup_field = 'id'
    fielddata = True
    filter_backends = [
        FilteringFilterBackend,
        OrderingFilterBackend,
        CompoundSearchFilterBackend,
    ]
    # 在全文中搜索范围的字段配置(模糊匹配)
    # Define filtering fields
    filter_fields = {
        'title': 'title',
        'content': 'content',
        # 'id': 'id',
    }
    # Define search fields
    search_fields = (
        # 'id',
        'title',
        'content',
    )
    # Define ordering fields
    ordering_fields = {
        'id': None,
    }
    # 指定默认顺序
    ordering = ('id', 'content')

    # 支持多个参数
    multi_match_search_fields = (
        'title',
        'content',
    )


# 测试
def update_data(request):
    # 群更新会触发
    # query = ElasticNews.objects.all()
    # for item in query:
    #     item.title = 'uuuuuuuuuuu'
    #     item.save()

    # 单更新会触发
    # obj = ElasticNews.objects.filter(id=3).first()
    # obj.title = '刘亚萍99999999999'
    # obj.save()

    # create会触发
    # ElasticNews.objects.create(title='cas', content='222', price='85')
    # ElasticNews.objects.create(title='多对多', content='cas', price='85')
    ElasticNews.objects.create(title='cas', content='csa', price='85')
    # ElasticNews.objects.create(title='cas2', content='lcas', price='85')

    # 删除
    # ElasticNews.objects.filter(id=4).delete()

    # update不会触发es与mysql同步,也不会触发信号post_save
    # ElasticNews.objects.filter(id=1).update(title='圆梦去', content='222', price='85')
    return JsonResponse({'status': 200})

# 修改 ulrpatterns

from django.contrib import admin
from django.urls import path
from news.views import *

urlpatterns = [
    path('admin/', admin.site.urls),
    path('search/', PublisherDocumentView.as_view({'get': 'list'})),
    path('add/', index),
    path('update/', update_data),
]

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

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

 # 访问 

http://127.0.0.1:8000/
http://127.0.0.1:8000/search/

查询使用 

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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐