django-haystack實現(xiàn)簡單接口的全文搜索.md

[圖片上傳中。。。(1)] [toc]

0 依賴的類庫

  • 搜索引擎:Whoosh這是一個由純Python實現(xiàn)的全文搜索引擎,沒有二進制文件等,比較小巧,配置比較簡單,當然性能自然略低.
  • 應用框架:django-haystack,用來實現(xiàn)django和搜索引擎之間的鏈接,由于只支持英文分詞,用jieba分詞代替.
  • 分詞工具: jieba分詞,他的ChineseAnalyzer 支持 Whoosh 搜索引擎.
pip install Whoosh jieba django-haystack

1 django-haystack配置.

1.1 setting中添加配置

配置Django項目的settings.py里面的 INSTALLED_APPS

INSTALLED_APPS = [ 
        'django.contrib.admin',
        'django.contrib.auth', 
        'django.contrib.contenttypes', 
        'django.contrib.sessions', 
        'django.contrib.sites', 

          # haystack先添加,
          'haystack', 
          # Then your usual apps... 自己的app要寫在haystakc后面
          'blog',
]

因為是要修改源碼,要添加修改了haystack的文件進入環(huán)境變量中:
比如,我把要修改的源碼的包都放在extra_apps中
在setting中加

sys.path.append(os.path.join(BASE_DIR, "extra_apps"))

django-haystack的搜索引擎設置,以及索引儲存的位置
在setting中加

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
    },
}

1.2 修改django-haystack的分詞器

找到源碼中的whoosh_backend.py文件

# 引入
from jieba.analyse import ChineseAnalyzer
#將StemmingAnalyzer()替換為 ChineseAnalyzer()
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer()), field_boost=field_class.boost, sortable=True)

下面就可以正常配置

2 索引的建立

如果你想針對某個app例如newapp做全文檢索,則必須在newapp的目錄下面建立search_indexes.py文件,文件名不能修改。內(nèi)容如下:

from haystack import indexes
from myapp.models import Hospital

class SetMealIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)  # 必須要建立全文搜索的字段
     # items為model中的字段
    items = indexes.MultiValueField(indexed=True, stored=True)    # 這是個多對多的鍵

    def get_model(self):
        # 用于搜索的model
        return SetMeal

    def index_queryset(self, using=None):
       # 得到特定條件的queryset
        return self.get_model().objects2api.all()

    def prepare_category(self, obj):
        # 得到多對多鍵的項目的name
       return [item.name for item in obj.items.all()]

class HospitalIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        return Hospital

    def index_queryset(self, using=None):
        return self.get_model().objects2api.all()

每個索引里面必須有且只能有一個字段為document=True,這代表haystack 和搜索引擎將使用此字段的內(nèi)容作為索引進行檢索(primary field)。其他的字段只是附屬的屬性,方便調(diào)用,并不作為檢索數(shù)據(jù)。

  • 數(shù)據(jù)模板

路徑為yourapp/templates/search/indexes/yourapp/yourmodel_text.txt

我這邊可以沒用到就隨便寫了一下

<h1>{{ object.name }}</h1>{{ object.description }}{{ object.price }}{{ object.fit_gender }}{% for item in object.items.all %}{{ item.name }}{% endfor %}

最后建立索引

python manage.py rebuild_index

3 接口代碼

class SearchSetMealListViewSet(mixins.ListModelMixin,                                                      viewsets.GenericViewSet):   serializer_class = SearchSetMealSerializer   pagination_class = StandardResultsSetPagination   def list(self, request, *args, **kwargs):       q = request.GET.get('q', '')       # todo優(yōu)化分詞方法       s = SearchQuerySet()       sqs = s.auto_query(q)       province = request.region.province       city = request.region.city       q1 = Q(hospitals__province=province, hospitals__city=city)       q2 = Q(hospitals__province='', hospitals__city='')       sqs = sqs.filter(q1 | q2).models(SetMeal)  # 過濾特定的model       page = self.paginate_queryset(sqs)       if page is not None:           serializer = self.get_serializer([i.object for i in page if i.object], many=True)           return self.get_paginated_response(serializer.data)       serializer = SearchSetMealSerializer([i.object for i in sqs if i.object], many=True, context={'request': request})       return Response(serializer.data)

索引的更新

因為實時的更新太過于消耗資源了,采用celery的周期任務,周期定為10分種

@task()
def update_index():
    logger.info('--------------更新索引開始--------------')
    from haystack.management.commands import update_index
    update_index.Command().handle()
    logger.info('--------------更新索引結(jié)束--------------')

django-celery不在這里詳細說明了,請百度.提醒一點
運行一般需要兩行命令,不僅僅需要celery beat.

python manage.py celery beat
python manage.py celery worker
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容