Django와elasticsearch 검색엔진 사이트 백엔드 기능을 통해 사고방식을 실현하다

13375 단어 py
1. 입력 상자 스마트 알림(es는 인터페이스를 제공) type을 수정하려면 마핑에 하나의 필드suggest를 설정해야 합니다. {"type":"completion"} 그래서 우리가 정의한 type을 수정해야 합니다. type에 새로운 필드:suggest,es-dsl 원본에 문제가 있기 때문에 이러한 정의는 틀릴 수 있습니다. CustomAnalyzer를 스스로 정의하고 사용자 정의 대상을 설명해야 합니다.ikanalyzer, type의 suggest에 대상을 부여합니다.
...
from elasticsearch_dsl.analysis import CustomAnalyzer as _CustomAnalyzer

class CustomAnalyzer(_CustomAnalyzer):

    def get_analysis_definition(self):
        #  , 
        return ()


#  , ik_max_word 
ik_analyzer = CustomAnalyzer('ik_max_word', filter=['lowercase'])


class DuowanType(DocType):
 ...
    #  suggest 。
    #  es-dsl , , CustomAnalyzer
    suggest = Completion(analyzer=ik_analyzer)
 ...

save에서 suggest 값 생성to_es에서 검색을 생성하려면suggest의 인터페이스를 생성해서 자신의 구조를 만들어야 합니다.items 클래스에서 전역 함수gen 정의하기suggests, index와 info 전달tuple은 weight 정보에 사용되고, 새 set은 무거운 것을 제거하는 데 사용되며,suggest 그룹은 되돌아오는 내용을 저장하는 데 사용됩니다.infotuple,text 문자열이 비어 있지 않으면,es의analyze 인터페이스를 호출하여 문자열을 분석하고 되돌려야 할 구조를 정리합니다
def gen_suggests(index, info_tuple):  #  tuple  weight   
    #  
    uesd_words = set()  #  
    suggests = []  #  
    for text, weight in info_tuple:
        if text:  #  
            #  es analyze 
            words = es.indices.analyze(index=index, analyzer='ik_max_word', params={'filter': ['lowercase']}, body=text)
            anylyzed_words = set(r["token"] for r in words["tokens"] if len(r["token"]) > 1)  #  
            new_words = anylyzed_words - uesd_words  #  
        else:
            new_words = set()
        if new_words:
            suggests.append({'input': list(new_words), 'weight': weight})  
    return suggests

그리고 save에서...to_es에서 이 함수를 호출합니다:
info_tuple = ((duowan.title, 10), (duowan.author, 7))
        duowan.suggest = (gen_suggests(DuowanType._doc_type.index, info_tuple))

django 검색 사이트를 구축하여 새로운 가상 환경을 만들고 가상 환경에 들어가서django 패키지pip install -i https://pypi.douban.com/simple/ django를 설치한 다음pycharm로django 프로젝트를 새로 만들고 직접 실행하면log에서 서버 주소를 볼 수 있습니다.static 디렉터리를 새로 만들고 css, html, js 파일을 붙여넣고 html 파일을templates 디렉터리에 붙여넣습니다.urls 파일에 url 추가
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]

settings에 줄 설정 추가하기;
#  tuple  tuple 
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')  #  
]

index에서.html에서 같은 가져오기 css와 js의 문장을
{% load staticfiles %}

...

...

이렇게 하면 settings의staticurljoin은''내용 앞에 가면 html 파일을 찾을 수 있습니다.
검색은 가상 환경에 같은 버전의 es-dsl f 모호한 검색fuzzy를 설치하는 것을 권장합니다:
GET duowan/video/_search
{
  "query": {
    "fuzzy": {
      "title": {
        "value": " ",
        "fuzziness": 2,
        "prefix_length": 3
      }
    }
  },
  "_source": ["title"]
}

fuzziness: 거리 편집prefixlength: 앞에 있는 변환에 참여하지 않는 단어의 길이 "source": ["title"]: 필드를 나타냅니다.
suggest:
POST duowan/video/_search
{
  "suggest": {
    "my-suggest": {
      "text":"PVQ",
      "completion": {
        "field": "suggest",
        "fuzzy": {
          "fuzziness":1
        }
      }
    }
  },
  "_source": ["title"]
}

my-suggest 사용자 정의 가능,field 변경 불가,
index에서.html 파일에 js 스크립트가 삽입되어 있으며 input 이벤트가 연결되어 있습니다. 그 안의 내용이 변할 때 서버에 요청을 보냅니다. 파라미터는 input 내용과 type 형식을 포함합니다.
$(function(){
        $('.searchInput').bind(' input propertychange ',function(){
            var searchText = $(this).val();
            var tmpHtml = ""
            $.ajax({
                cache: false,
                type: 'get', //get 
                dataType:'json',
                url:suggest_url+"?s="+searchText+"&s_type="+$(".searchItem.current").attr('data-type'),
                async: true,
                success: function(data) {
                    for (var i=0;i'+data[i]+''
                    }
                    $(".dataList").html("")
                    $(".dataList").append(tmpHtml);
                    if (data.length == 0){
                        $('.dataList').hide()
                    }else {
                        $('.dataList').show()
                    }
                }
            });
        } );
    })

urls에 새로 추가된 내용:
 url(r'^suggest/$', TemplateView.as_view(template_name='index.html'), name='index')

그리고 파충 파일의 es-type 내용을django 프로젝트의 모델로 복사해서views 파일을 편집합니다.
import json
from django.shortcuts import render
from django.views.generic.base import View
from search.models import DuowanType
from django.http import HttpResponse


# Create your views here.
#   View
class SearchSuggest(View):
    def get(self, request):
        key_words = request.GET.get('s', '')  #  request s  
        re_dates = []  #  title
        if key_words:
            s = DuowanType.search()
            #  
            s = s.suggest('my_suggest', key_words, completion={
                "field": "suggest",
                "fuzzy": {
                    "fuzziness": 2
                },
                "size": 10
            })
            #  
            suggestions = s.execute_suggest()
            for match in suggestions.my_suggest[0].options:
                source = match._source
                re_dates.append(source['title'])
        #  HttpResponse , json 
        return HttpResponse(json.dumps(re_dates), content_type='application/json')

urls에 있는
 url(r'^suggest/$', TemplateView.as_view(template_name='index.html'), name='index')

... 로 바꾸다
    url(r'^suggest/$', SearchSuggest.as_view(), name='suggest')


Search Suggest였던 기억이 나요.as_view (), SearchSuggest가 아닙니다.as_view, 그렇지 않으면 다음과 같이 잘못 보고됩니다: TypeError: asview() takes 1 positional argument but 2 were given
2 검색 기능 urls:
from search.views import SearchSuggest, SearchView
...
url(r'^search/$', SearchView.as_view(), name='search')

views에SearchView(View)를 추가합니다. 전송된 검색 키워드 매개 변수와 페이지 매개 변수를 받아서client 연결es 서버를 만들고client를 사용합니다.검색은 원시적인 문장을 실행할 수 있으며,client를 사용합니다.검색어를 실행하고, 되돌아오는 값을 받고, 되돌아오는 결과를 꺼내서list에 저장하고, 마지막으로render로 페이지에 되돌려줍니다. 검색 시간:client를 기록합니다.검색 운행 전후 시간, 다시 감법
from elasticsearch import Elasticsearch
from datetime import datetime
client = Elasticsearch(hosts='127.0.0.1')
.......
class SearchView(View):
    def get(self, request):
        key_words = request.GET.get('q', '')
        pagesize = 10
        page = request.GET.get('p', '')
        try:
            page = int(page)
        except:
            page = 1

        # client.search 
        body = {
                "query": {
                    "multi_match": {
                        "query": key_words,
                        "fields": ["title", "author"]
                    }
                },
                "from": (page-1)*pagesize,
                "size": pagesize,
                #    highlight 
                "highlight": {
                    #  html tag tag 
                    "pre_tags": [""],
                    "post_tags": [""],
                    "fields": {
                        "title": {},
                        "content": {}
                    }
                }
            }
        start_time = datetime.now()
        response = client.search(
            index="duowan",
            body=body
        )
        end_time = datetime.now()
        last_seconds = (end_time-start_time).total_seconds()
        #  
        total_nums = response['hits']['total']
        if (page % 10) > 0:
            page_nums = int(total_nums/10)+1
        else:
            page_nums = int(page/10)
        #      html
        hit_list = []
        for hit in response['hits']['hits']:
            hit_dict = {}
            if 'title' in hit['highlight']:
                 hit_dict['title'] = hit['highlight']['title'][0]
            else:
                #   hit_dict['title'] = hit['_source']['title'][:100
                hit_dict['title'] = hit['_source']['title']
            hit_dict['len'] = hit['_source']['len']
            hit_dict['tag'] = hit['_source']['tag']
            hit_dict['update_time'] = hit['_source']['update_time']
            hit_dict['author'] = hit['_source']['author']
            hit_dict['playnum_text'] = hit['_source']['playnum_text']
            hit_dict['url'] = hit['_source']['url']
            hit_list.append(hit_dict)
        return render(request, 'result.html', {'page': page,
                                               'total_nums': total_nums,
                                               'all_hits': hit_list,
                                               'key_words': key_words,
                                               'page_nums': page_nums,
                                               'last_seconds': last_seconds})

페이지에서:item의div를 찾아 {% for hit in all_hits %} ... {% endfor %}로 for 순환을 사용하여 전송된 검색 결과list allhits.페이지에 값 채우기
   {% for hit in all_hits %}
                    
{{ hit.title }} - {{ hit.tag }} {{ hit.playnum_text }}
{{ hit.update_time }}
{% endfor %}

js로 검색 기록 구현: 검색 단추를 눌렀을 때dd 터치검색 () 방법으로 키워드를 얻고 Kill Repeat () 로 검색 기록을 다시 한 번 지우고, 다시 한 번 브라우저local Storage에 저장한 다음 검색 내용을 표시합니다.
// 
    function add_search(){
        var val = $(".searchInput").val();
        if (val.length>=2){
            // , 
            KillRepeat(val);
            // localStorage
            localStorage.search = searchArr;
            // 
            MapSearchArr();
        }

        window.location.href=search_url+'?q='+val+"&s_type="+$(".searchItem.current").attr('data-type')

    }

    function MapSearchArr(){
        var tmpHtml = "";
        var arrLen = 0
        if (searchArr.length >= 5){
            arrLen = 5
        }else {
            arrLen = searchArr.length
        }
        // html 
        for (var i=0;i'+searchArr[i]+''
        }
        $(".mysearch .all-search").html(tmpHtml);
    }
    //   , 
    function KillRepeat(val){
        var kill = 0;
        for (var i=0;i

좋은 웹페이지 즐겨찾기