zoukankan      html  css  js  c++  java
  • django internal search

    最近改进了项目中的站内搜索的功能,增加了全文索引,提升了搜索速度。因为项目框架是django,所以采用django+haystack+pyelasticsearch+elasticsearch的方式实现。

    django作为Web framework,采用MVC设计模式,非常易于开发数据库驱动的网站。

    haystack是django的搜索插件,提供一套统一的API,用于驱动搜素引擎创建索引,进行搜素。可适用的搜素引擎包括whoosh,ES,Solr等。

    pyelasticsearch主要提供python语言调用elasticsearch的Client类。

    elasticsearch是一款开源的分布式搜素引擎,具备高可靠性,支持非常多的企业级搜索用例

    本项目采用:

    django-1.5.0

    haystack-2.0.0

    pyelasticsearch-0.5

    elasticsearch-1.5.0

    笔者在实践过程中发现haystack与pyelasticsearch不同版本下协同工作并不一定能成功,有可能报错:

    org.elasticsearch.indics.InvalidTypeNameException:mapping type name [_mapping] can't start with '_'

    这是haystack创建索引过程中,传入了pyelasticsearch无法解析的dict,通过搜索和尝试,基本确定了上面的版本在Windows7操作系统下能够正常工作。

    环境的安装去配置不再累述,用pip命令进行安装非常简单,网上也有很多例子。

    进行搜索之前,必须针对数据库视图创建索引,要支持全文搜索,必须对除主键外的字段,特别是类似summary, comment, destription之类的字段创建索引。

    haystack创建索引有其固有的格式:

    首先,为欲搜索的model创建索引类,这个索引类用于haystack创建索引文件,也用于搜索过程中haystack API进行搜索。

    class IncidentIndex(indexes.SearchIndex, indexes.Indexable):
        text                = indexes.CharField(document=True,use_template=True)
        incident_number     = indexes.CharField(model_attr='incident_number')
        incident_summary    = indexes.CharField(model_attr='summary',null=True)
        notes               = indexes.NgramField(model_attr='notes',null=True)
        reported_date       = indexes.DateTimeField(model_attr='reported_date')
    
        def get_model(self):
            return Incident
    
        def index_queryset(self, using=None):
            """Used when the entire index for model is updated."""
            return self.get_model().objects.all()  

    实例代码是项目中为Incidnet model创建索引类的实现:

    索引类要继承 indexes.SearchIndex, indexes.Indexable 类,这样索引类就能够像Django的Model类一样提交到后端。

    每一个索引类必须至少包含一个document=True的字段以支持基于文件的查找,而这个字段也是search engine主要查找的字段。

    Search Field有很多种,常用的CharField,BooleanFeild, DateFeild,IntergeFeild, NgramField,EdgeNgramField在Haystack官网上都有详细的介绍。重点强调一点,如果想输入的词组作为固定的短语进行查询,则字段用CharFeild,如果想输入的词组分词为每个独立的单词进行查询,则字段用NgramField。

    null=True用于在创建索引的过程中忽略记录为空的情况。

    index_queryset方法用于返回实际的类对象。

    创建好索引类之后,要在templates/search/indexs/{AppName}/路径下创建对应索引类的{classname}_text.txt文件,对应索引类中text字段的查询内容。

    例如,incident_text.txt:

    {{ object.incident_number }}
    {{ object.incident_summary }}

    用于基于文件的快速检索。

    在创建好索引类和相应的基于文件检索的txt文件之后,可以通过manage.py调用haystack的命令创建索引,此时保证elasticsearch是打开的,并且处于默认的进程号9200。

    打开ES:click elasticsearchinelasticsearch.bat

    创建索引:python manage.py rebuild_index

    如果model类更新了,则需要更新索引,可采用命令:python manage.py update_index

    需要指出,haystack提供了一种实时自动更新索引的方法,即在索引类定义时,用indexes.RealTimeSearchIndex类代替indexes.SearchIndex,但是更新索引是比较耗时的,并不建议涉及大量用户的网站使用该方法。

    创建索引成功之后,就可以在项目中通过调用haystack提供的方法实现search了。

    haystack提供了强大的API,用于实现查询,而且API的使用与django API非常相似。主要包括SearchQuerySet API, SearchResult API, SearchQuery API, Input Types, SearchBackend API和上文提到的SearchField API与SearchIndex API。具体使用参见haystack,本文仅列举某些常用API。

    SearchQuerySet API提供一个类似于django's ORM QuerySet的查询类,同样具有all,filter,exclude等查询方法用于查询索引。

    e.g.

    results = SearchQuerySet().filter(incident_number=Exact(query)).highlight()

    SearchQuery API 提供一个SQ对象,类似于django的Q,用于组合查询条件。

    e.g.

     results = SearchQuerySet().filter(SQ(incident_summary=Exact(query)) | SQ(change_summary=Exact(query)) | SQ(wo_summary=Exact(query)) | SQ(task_summary=Exact(query)) ).highlight()

    Input Types允许developer指定一个advance的查询条件,比如:

    Exact:确保输入的短语Exactly matched。

    Clean: 确保特殊字符的输入能够得到正确的解释,比如url中:和/的escape

    -------------------------------- 分割线 ----------------------------------------

    今天在QA环境上部署了一把,QA环境是VM,OS是centos-6.3 , django-1.6.5 .

    当使用haystack-2.0.0的时候报错:

    'SearchNode' object has no attribute 'start_subtree'

    通过把haystack替换成2.1.0版本,解决了这个问题。

    在进行查询的时候,又报了错:

    Failed to query Elasticsearch using '( OR change_summary:("telephony"))': Non-OK response returned (400): u'SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; 

    不知道什么情况,索性把setting配置改为:

    HAYSTACK_DEFAULT_OPERATOR = 'AND'

    嘿嘿,解决了这个问题。

    reference:

    http://django-haystack.readthedocs.org/en/latest/

  • 相关阅读:
    VS2005在使用membership的时候,如何连接Access数据库?
    今天想开始写计划的项目,可是就是静不下心来,乱糟糟的!
    今天想开始写计划的项目,可是就是静不下心来,乱糟糟的!
    有钱真好
    网页左边和上面的空隙如何设置成为0
    vim 配色方案(目测有上百个)
    Git 远程仓库的管理和使用
    vim 使用图
    Python 编程挑战
    python 网络爬虫
  • 原文地址:https://www.cnblogs.com/zhq1007/p/4395543.html
Copyright © 2011-2022 走看看