欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何集成Elasticsearch到django restful

 更新時間:2024年09月29日 11:27:23   作者:叫我DPT  
在Django項目中集成Elasticsearch可通過Haystack實現(xiàn),Haystack作為Django插件提供搜索接口,Elasticsearch作為后端搜索引擎存儲檢索數(shù)據(jù),Haystack支持多種搜索引擎,易于切換且不需改動代碼,本文給大家介紹如何集成Elasticsearch到django restful,感興趣的朋友一起看看吧

集成ES到django restful服務(wù)端項目

如果直接在Django項目直接編寫代碼作為ElasticSearch的客戶端,比較復(fù)雜,所以借助第三方包Haystack來對接ELasticSearch的客戶端。而且使用了Haystack后,以后你換其他的全文搜索服務(wù)器時,也不用修改Django項目已經(jīng)寫好的代碼。

安裝haystack

Haystack ,Django ,Elasticsearch 三者之間的關(guān)系是:

  • Haystack 作為 Django 的一個插件,提供了一個 Django 應(yīng)用接口來實現(xiàn)搜索功能。
  • Elasticsearch 作為 Haystack 支持的搜索引擎之一,可以被 Haystack 用來作為后端搜索引擎來存儲和檢索數(shù)據(jù)。
  • 當(dāng)你在 Django 項目中使用 Haystack 并選擇 Elasticsearch 作為搜索引擎時,Haystack 會作為中間層,讓你能夠通過 Django 的視圖和模板來操作 Elasticsearch,實現(xiàn)全文搜索的功能。

簡單來說,Haystack 為 Django 提供了搜索功能的抽象層,而 Elasticsearch 是這個抽象層背后的具體實現(xiàn)之一。通過 Haystack,你可以在 Django 項目中輕松地實現(xiàn)強大的搜索功能。

haystack是django的開源搜索框架,能夠結(jié)合目前市面上大部分的搜索引擎用于實現(xiàn)自定義搜索功能,特別是全文搜索。

haystack支持多種搜索引擎,不僅僅是 jieba ,whoosh,使用solr、elasticsearch等搜索,也可通過haystack,而且直接切換引擎即可,甚至無需修改搜索代碼。中文分詞最好的就是jieba和elasticsearch+ik。

github: https://github.com/rhblind/drf-haystack

# python操作elasticsearch的模塊,注意對應(yīng)版本,類似pymysql
pip install -U elasticsearch==7.13.4
# django開發(fā)的haystack的模塊,務(wù)必先安裝drf`-haystack,接著才安裝django-haystack。因為drf-haystack不支持es7
pip install -U drf-haystack
pip install -U django-haystack

基本使用

安裝配置

文檔:https://drf-haystack.readthedocs.io/en/latest/01_intro.html#examples

INSTALLED_APPS = [
	# 必須在自己創(chuàng)建的子應(yīng)用前面
	'haystack',
	# 自己創(chuàng)建的子應(yīng)用
]
# haystack連接elasticsearch的配置信息
HAYSTACK_CONNECTIONS = {
    'default': {
        # haystack操作es的核心模塊
        'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine',
        # es服務(wù)端地址
        'URL': 'http://127.0.0.1:9200/',
        # es索引倉庫
        'INDEX_NAME': 'haystack',
    },
}
# 當(dāng)mysqlORM操作數(shù)據(jù)庫改變時,自動更新es的索引,否則es的索引會找不到新增的數(shù)據(jù)
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

索引模型

在courses子應(yīng)用下創(chuàng)建search_indexes.py,用于設(shè)置es的索引模型。注意,索引模型的文件名必須是search_indexes。

  • 類名必須為需要檢索的Model_name+Index
  • 每個索引里面必須有且只能有一個字段為 document=True,這代表haystack 和搜索引擎將使用此字段的內(nèi)容作為索引進行檢索(primary field)。其他的字段只是附屬的屬性,方便調(diào)用,并不作為檢索數(shù)據(jù)。
  • 如果使用一個字段設(shè)置了document=True,則一般約定此字段名為text,這是在SearchIndex類里面一貫的命名,以防止后臺混亂,當(dāng)然名字你也可以隨便改,不過不建議改。
  • haystack提供了use_template=True在text字段,這樣就允許我們使用數(shù)據(jù)模板去建立搜索引擎索引的文件,說得通俗點就是索引里面需要存放一些什么東西
  • text字段用于構(gòu)造索引,只不過具體構(gòu)造索引的值寫在另一個文件內(nèi)。
  • id、title、digest、content、image_url等字段用于以索引查詢到的返回內(nèi)容。
  • get_model方法用于指明建立索引的對應(yīng)模型。
  • index_queryset方法用于返回建立索引的數(shù)據(jù)查詢集。
from haystack import indexes
from .models import Course
class CourseIndex(indexes.SearchIndex, indexes.Indexable):
    # 全文索引[可以根據(jù)配置,可以包括多個字段索引]
    # document=True 表示當(dāng)前字段為全文索引
    # use_template=True 表示接下來haystack需要加載一個固定路徑的html模板文件,讓text與其他索引字段綁定映射關(guān)系
    text = indexes.CharField(document=True, use_template=True)
    # 普通索引[單字段,只能提供單個字段值的搜索,所以此處的聲明更主要是為了提供給上面的text全文索引使用的]
    # es索引名 = indexes.索引數(shù)據(jù)類型(model_attr="ORM中的字段名")
    id = indexes.IntegerField(model_attr="id")
    name = indexes.CharField(model_attr="name")
    description = indexes.CharField(model_attr="description")
    teacher = indexes.CharField(model_attr="teacher__name")
    course_cover = indexes.CharField(model_attr="course_cover")
    get_level_display=indexes.CharField(model_attr="get_level_display")
    students=indexes.IntegerField(model_attr="students")
    get_status_display=indexes.CharField(model_attr="get_status_display")
    lessons=indexes.IntegerField(model_attr="lessons")
    pub_lessons=indexes.IntegerField(model_attr="pub_lessons")
    price=indexes.DecimalField(model_attr="price")
    discount=indexes.CharField(model_attr="discount_json")
    orders=indexes.IntegerField(model_attr="orders")
    # 指定與當(dāng)前es索引模型對接的mysql的ORM模型
    def get_model(self):
        return Course
    # 當(dāng)用戶搜索es索引時,對應(yīng)的提供的mysql數(shù)據(jù)集有哪些?
    def index_queryset(self, using=None):
        return self.get_model().objects.filter(is_deleted=False,is_show=True)

ORM模型中新增discount_json字段方法

courses.models,代碼:

import json
class Course(BaseModel):
    course_type = (
        (0, '付費購買'),
        (1, '會員專享'),
        (2, '學(xué)位課程'),
    )
    level_choices = (
        (0, '初級'),
        (1, '中級'),
        (2, '高級'),
    )
    status_choices = (
        (0, '上線'),
        (1, '下線'),
        (2, '預(yù)上線'),
    )
    # course_cover = models.ImageField(upload_to="course/cover", max_length=255, verbose_name="封面圖片", blank=True, null=True)
    course_cover = StdImageField(variations={
        'thumb_1080x608': (1080, 608),   # 高清圖
        'thumb_540x304': (540, 304),    # 中等比例,
        'thumb_108x61': (108, 61, True),  # 小圖(第三個參數(shù)表示保持圖片質(zhì)量),
    }, max_length=255, delete_orphans=True, upload_to="course/cover", null=True, verbose_name="封面圖片",blank=True)
    course_video = models.FileField(upload_to="course/video", max_length=255, verbose_name="封面視頻", blank=True, null=True)
    course_type = models.SmallIntegerField(choices=course_type,default=0, verbose_name="付費類型")
    level = models.SmallIntegerField(choices=level_choices, default=1, verbose_name="難度等級")
    description = RichTextUploadingField(null=True, blank=True, verbose_name="詳情介紹")
    pub_date = models.DateField(auto_now_add=True, verbose_name="發(fā)布日期")
    period = models.IntegerField(default=7, verbose_name="建議學(xué)習(xí)周期(day)")
    attachment_path = models.FileField(max_length=1000, blank=True, null=True, verbose_name="課件路徑")
    attachment_link = models.CharField(max_length=1000, blank=True, null=True, verbose_name="課件鏈接")
    status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="課程狀態(tài)")
    students = models.IntegerField(default=0, verbose_name="學(xué)習(xí)人數(shù)")
    lessons = models.IntegerField(default=0, verbose_name="總課時數(shù)量")
    pub_lessons = models.IntegerField(default=0, verbose_name="已更新課時數(shù)量")
    price = models.DecimalField(max_digits=10,decimal_places=2, verbose_name="課程原價",default=0)
    recomment_home_hot = models.BooleanField(default=False, verbose_name="是否推薦到首頁新課欄目")
    recomment_home_top = models.BooleanField(default=False, verbose_name="是否推薦到首頁必學(xué)欄目")
    direction = models.ForeignKey("CourseDirection", related_name="course_list", on_delete=models.DO_NOTHING, null=True, blank=True, db_constraint=False, verbose_name="學(xué)習(xí)方向")
    category = models.ForeignKey("CourseCategory", related_name="course_list", on_delete=models.DO_NOTHING, null=True, blank=True, db_constraint=False, verbose_name="課程分類")
    teacher = models.ForeignKey("Teacher", related_name="course_list", on_delete=models.DO_NOTHING, null=True, blank=True, db_constraint=False, verbose_name="授課老師")
    class Meta:
        db_table = "fg_course_info"
        verbose_name = "課程信息"
        verbose_name_plural = verbose_name
    def __str__(self):
        return "%s" % self.name
    def course_cover_small(self):
        if self.course_cover:
            return mark_safe(f'<img style="border-radius: 0%;" src="{self.course_cover.thumb_108x61.url}">')
        return ""
    course_cover_small.short_description = "封面圖片(108x61)"
    course_cover_small.allow_tags = True
    course_cover_small.admin_order_field = "course_cover"
    def course_cover_medium(self):
        if self.course_cover:
            return mark_safe(f'<img style="border-radius: 0%;" src="{self.course_cover.thumb_540x304.url}">')
        return ""
    course_cover_medium.short_description = "封面圖片(540x304)"
    course_cover_medium.allow_tags = True
    course_cover_medium.admin_order_field = "course_cover"
    def course_cover_large(self):
        if self.course_cover:
            return mark_safe(f'<img style="border-radius: 0%;" src="{self.course_cover.thumb_1080x608.url}">')
        return ""
    course_cover_large.short_description = "封面圖片(1080x608)"
    course_cover_large.allow_tags = True
    course_cover_large.admin_order_field = "course_cover"
    @property
    def discount(self):
        # todo 將來通過計算獲取當(dāng)前課程的折扣優(yōu)惠相關(guān)的信息
        import random
        return {
            "type": ["限時優(yōu)惠","限時減免"].pop(random.randint(0,1)), # 優(yōu)惠類型
            "expire": random.randint(100000, 1200000),  #  優(yōu)惠倒計時
            "price": float(self.price - random.randint(1,10) * 10),  # 優(yōu)惠價格
        }
    def discount_json(self):
        # 必須轉(zhuǎn)成字符串才能保存到es中。所以該方法提供給es使用的。
        return json.dumps(self.discount)

全文索引字段模板

全文索引模板必須先配置django項目中的TEMPLATES模板引擎路徑,而且全文索引模板的路徑必須是模板目錄下的search/indexes/子應(yīng)用目錄名/模型類名_text.txt。否則報錯。settings.dev,代碼:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            BASE_DIR / "templates",  # BASE_DIR 是apps的父級目錄,是主應(yīng)用目錄,templates需要手動創(chuàng)建
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

創(chuàng)建全文索引字段的html模板,在HTML模板中采用django的模板語法,綁定text與其他es單字段索引的映射關(guān)系。

注意:course_text.txt 中course就是ORM模型類名小寫,text就是es索引模型類中的全文索引字段名。

templates/search/indexes/courses/course_text.txt。代碼:

{{ object.name }}
{{ object.description }}
{{ object.teacher.name }}
{{ object.category.name }}
{{ object.diretion.name }}

object表示當(dāng)前orm的模型對應(yīng)。

索引序列化器

courses.serializers,代碼:

from drf_haystack.serializers import HaystackSerializer
from .search_indexes import CourseIndex
from django.conf import settings
class  CourseIndexHaystackSerializer(HaystackSerializer):
    """課程搜索的序列化器"""
    class Meta:
        index_classes = [CourseIndex]
        fields = ["text", "id", "name", "course_cover", "get_level_display", "students", "get_status_display", "pub_lessons", "price", "discount", "orders"]
    def to_representation(self, instance):
        """用于指定返回數(shù)據(jù)的字段的"""
        # 課程的圖片,在這里通過elasticsearch提供的,所以不會提供圖片地址左邊的域名的。因此在這里手動拼接
        instance.course_cover = f'//{settings.OSS_BUCKET_NAME}.{settings.OSS_ENDPOINT}/uploads/{instance.course_cover}'
        return super().to_representation(instance)

全文搜索的索引視圖

from drf_haystack.viewsets import HaystackViewSet
from drf_haystack.filters import HaystackFilter
from .serializers import CourseIndexHaystackSerializer
from .models import Course
class CourseSearchViewSet(HaystackViewSet):
    """課程信息全文搜索視圖類"""
    # 指定本次搜索的最終真實數(shù)據(jù)的保存模型
    index_models = [Course]
    serializer_class = CourseIndexHaystackSerializer
    filter_backends = [OrderingFilter, HaystackFilter]
    ordering_fields = ('id', 'students', 'orders')
    pagination_class = CourseListPageNumberPagination

路由

from django.urls import path,re_path
from . import views
from rest_framework import routers
router = routers.DefaultRouter()
# 注冊全文搜索到視圖集中生成url路由信息
router.register("search", views.CourseSearchViewSet, basename="course-search")
urlpatterns = [
    path("directions/", views.CourseDirectionListAPIView.as_view()),
    re_path("^categories/(?P<direction>\d+)/$", views.CourseCategoryListAPIView.as_view()),
    re_path("^(?P<direction>\d+)/(?P<category>\d+)/$", views.CourseListAPIView.as_view()),
] + router.urls

手動構(gòu)建es索引

因為此前mysql中已經(jīng)有了部分的數(shù)據(jù),而這部分?jǐn)?shù)據(jù)在es中是沒有創(chuàng)建索引。所以需要先把之前的數(shù)據(jù)同步生成全文索引。在終端下執(zhí)行以下命令

# 重建索引
python manage.py rebuild_index
# 更新索引
# python manage.py update_index --age=<num_hours>
# 刪除索引
# python manage.py clear_index

訪問

http://api.fuguang.cn:8000/courses/search/?text=入門

http://api.fuguang.cn:8000/courses/search/?text=李老師

到此這篇關(guān)于集成Elasticsearch到django restful的文章就介紹到這了,更多相關(guān)Elasticsearch集成django restful內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 戲說編碼發(fā)展史

    戲說編碼發(fā)展史

    本文從一個風(fēng)趣的角度詳細介紹了計算機編碼的發(fā)展歷史,十分的有趣,小伙伴們仔細研讀下吧,了解下相關(guān)知識也是非常有必要的。
    2015-01-01
  • 網(wǎng)頁報錯"Form?elements?must?have?labels"的處理方法

    網(wǎng)頁報錯"Form?elements?must?have?labels"的處理方法

    這篇文章主要給大家介紹了關(guān)于網(wǎng)頁報錯"Form?elements?must?have?labels"的處理方法,文中通過實例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2023-06-06
  • 關(guān)于爬蟲和反爬蟲的簡略方案分享

    關(guān)于爬蟲和反爬蟲的簡略方案分享

    這篇文章主要給大家介紹了一些關(guān)于爬蟲和反爬蟲的簡略方案的相關(guān)資料,文中介紹的非常詳細,對大家理解和學(xué)習(xí)爬蟲與反爬蟲具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Windows下使用Gogs搭建Git服務(wù)器

    Windows下使用Gogs搭建Git服務(wù)器

    這篇文章介紹了使用Gogs搭建Git服務(wù)器的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • AERGO SHIP:用于開發(fā)智能合約的包管理器

    AERGO SHIP:用于開發(fā)智能合約的包管理器

    AERGO SHIP:用于開發(fā)智能合約的包管理器,用于構(gòu)建、測試和部署分布式應(yīng)用程序的客戶端框架和開發(fā)環(huán)境
    2018-11-11
  • 學(xué)編程選什么語言好?是PHP、Python還是Ruby?

    學(xué)編程選什么語言好?是PHP、Python還是Ruby?

    這篇文章主要介紹了學(xué)編程選什么語言好?是PHP、Python還是Ruby?需要的朋友可以參考下
    2014-06-06
  • 使用git命令上傳代碼

    使用git命令上傳代碼

    這篇文章介紹了使用git命令上傳代碼的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • 21 歲理工男開源的這個編輯器火遍全球附面試資源

    21 歲理工男開源的這個編輯器火遍全球附面試資源

    最近在 GitHub 上最火的項目是一個對視力友好的十六進制編輯器,它上線僅 5 天就收獲了 2500 star,最近 24 小時漲了 1600 star 量,感興趣的朋友跟隨小編一起看看吧
    2020-12-12
  • Archlinux?Timeshift系統(tǒng)備份與還原的操作方法

    Archlinux?Timeshift系統(tǒng)備份與還原的操作方法

    這篇文章主要介紹了Archlinux?Timeshift系統(tǒng)備份與還原的操作方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • mathtype的下載與使用技巧超詳細教程

    mathtype的下載與使用技巧超詳細教程

    這篇文章主要介紹了mathtype的下載與使用超詳細教程,包括mathtype使用技巧常用快捷鍵,本文給大家講解的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01

最新評論