• django elasticsearch+docker实现搜索功能接口


    需求分析:

    可以使用数据库的模糊查询(like关键字)来实现,但效率极低

    在多个字段中查询,使用like关键字不方便

    因此使用搜索引擎来实现全文检索    (ES

    搜索引擎原理:

    搜索引擎并不是直接在数据库中进行查询

    会对数据库中的数据进行一遍预处理,单独建立一份索引结构数据

    类似字典的索引检索页

    Elasticsearch:

    开源

    搜索引擎

    首选底层是开源库Lucene

    REST API 的操作接口

    注意

    搜索引擎在对数据构建索引时,需要进行分词处理。分词是指将一句话拆解成多个单字或词,这些字或词便是这句话的关键词。

    Elasticsearch 不支持对中文进行分词建立索引,需要配合扩展elasticsearch-analysis-ik来实现中文分词处理。

    使用docker安装elasticsearch

     docker下载images

    docker image pull delron/elasticsearch-ik:2.4.6-1.0

    dockers load -i 也行

    修改配置

    在虚拟机中的elasticsearch/config/elasticsearch.yml第54行,更改ip地址为0.0.0.0,端口改为9200,默认端口为9200
    # network.host: 172.18.168.123
    network.host: 0.0.0.0
    #
    # Set a custom port for HTTP:
    #
    http.port: 9200   阿里云的话去转

    创建docker容器并运行

     冒号前半段是本地配置  后半段是docker的

    docker run -dti --network=host --name=elasticsearch -v       /home/pyvip/elasticsearch/config:/usr/share/elasticsearch/config      delron/elasticsearch-ik:2.4.6-1.0

    如果上面的不稳定,经常EXIT。那么可以使用下面这个进行启动

    docker run -dti --name=elasticsearch -p 9200:9200 delron/elasticsearch-ik:2.4.6-1.0

    使用elasticsearch

    进入项目虚拟环境中,安装相关包

    # 进入项目虚拟环境
    workon 【环境】
    
    # 如果安装报错,先初始化  pip3 install setuptools_scm
    pip3 install django-haystack
    pip3 install elasticsearch==2.4.1

     在Django里面的settings.py文件中加入如下配置:

    # 添加app功能
    INSTALLED_APPS = [ 'haystack', ] # Haystack引擎 HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', # 引擎 'URL': 'http://192.168.216.137:9200/', # 此处为elasticsearch运行的服务器ip地址,端口号默认为9200!!!!!!!!!! 'INDEX_NAME': 'site', # 指定elasticsearch建立的索引库的名称 !!!!!! 这里千万不能大写,统一小写,不然会出错的 }, } # 设置每页显示的数据量 HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5 # 当数据库改变时,会自动更新索引 HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

    后端实现elasticsearch模块

    建立索引index

    from haystack import indexes

    from news.models import News


    # 结构必须是跟models完全一直的 , Index必须是大写
    # SearchIndex和Indexable 都是index提供给我们的类
    # 类的命名是有要求的,首字母都是要大写
    # 如果是Comment的话那就是CommentIndex
    # 继承两个类Django的haystack提供的搜索基类
    # SearchIndex 是让模型和搜索引擎进行交互
    class NewsIndex(indexes.SearchIndex, indexes.Indexable):
    """
    News索引数据模型类
    """
    # 类 与 News模型进行一致
    # 搜索是需要模板的 template就是 Elasticsearch 和 haystack进行交互的字段
    # document 为与模型一致化的解析
    # use_template 是搜索需要模板
    text = indexes.CharField(document=True, use_template=True) # 很重要
    # 搜索引擎的字段与模型当中哪一个字段进行匹配。
    id = indexes.IntegerField(model_attr='id')
    title = indexes.CharField(model_attr='title')
    digest = indexes.CharField(model_attr='digest')
    content = indexes.CharField(model_attr='content')
    image_url = indexes.CharField(model_attr='image_url')

    def get_model(self):
    """
    返回建立索引的模型类
    我们的索引类是使用哪一个模型的再去模型里面找对应model_attr
    :return:
    """
    return News

    # 返回一个查询集
    def index_queryset(self, using=None):
    """
    返回要建立索引的数据查询表
    :param using:
    :return:
    self.get_model()返回News
    """
    return self.get_model().objects.filter(is_delete=False)
    # 在manage中执行如下命令,生成索引

    python manage.py -h 可以查找关于haystack的命令 重新建立
    python manage.py rebuild_index

    更新命令
    pyhton manage.py update_index
    这里的路径千万不能错!     news_text.txt 里面的news是模型的小写形式  如果这里写错,rebuild_index会寻找不了news_text.txt

    #
    创建templates/search/indexes/news/news_text.txt文件(文件名为:模型_text.txt) # 此模板指明当将关键词通过text参数名传递时,可以通过news 的title、digest、content 来进行关键字索引查询 {{ object.title }} {{ object.digest }} {{ object.content }}

    视图逻辑功能:

    1. 判断接受参数q(默认为q)是否有值,并且传入show_all里面。有则调用父类create_response(下面有源码介绍),没有则直接展示热门信息或者其他自定义。

    2. 重写template

    3. 使用paginator

    
    
    from haystack.views import SearchView as _SearchView
    class SearchView(_SearchView):
        # 重写template
        template = 'news/search.html'
        # 重写响应方式,如果请求参数为空, 返回模型News的热门新闻数据,否则就根据q是什么再去查
        def create_response(self):
            default_page = 1
            # q是haystack定义好的
            kw = self.request.GET.get('q', '')
            # 是否Show_all
            # 以下定义的变量paginator   page 都不能改
            if not kw:
                show_all = True
                hot_news = models.HotNews.objects.select_related('news').only('news_id', 'news__title', 'news__image_url'). 
                               filter(is_delete=False).order_by('priority')
                paginator = Paginator(hot_news, HAYSTACK_SEARCH_RESULTS_PER_PAGE)
                try:
                    page = paginator.page(int(self.request.GET.get('page', default_page)))
                    # 防止传的是a,b,c
                except PageNotAnInteger:
                    page = paginator.page(default_page)
                except EmptyPage:
                    # 如果访问的是大于最后一页,那么返回最后一页的数据 num_pages就是总页数,也就是最后一页
                    page = paginator.page(paginator.num_pages)
                return render(self.request, self.template, locals())
            else:
    # 源码context = { # 'query': self.query, # 'form': self.form, # 'page': page, # 'paginator': paginator, # 'suggestion': None, # } # 父类的create_response已经帮你做好了 将上面的context 放到template当中 # 这上面的query就是个他妈的关键字 show_all = False queryset = super(SearchView, self).create_response() return queryset
  • 相关阅读:
    phpstorm设置内存限制的方法
    PHP str_replace的用法
    php PDO getlastsql写法
    css3 transform做动画
    PHP判断是否关注微信公众号
    nginx目录安全设置
    BaseAdapter自定义适配器——思路详解
    sys.path
    plt.rcParams[]
    %matplotlib inline
  • 原文地址:https://www.cnblogs.com/jackson669/p/12559634.html
Copyright © 2020-2023  润新知