如何使搜索自动完成更快?

时间:2013-08-15 05:41:17

标签: php jquery caching autocomplete memcached

我使用jQuery自动完成实现了一个基本的自动完成功能。我每次都在查询DB,这使得自动完成的东西很慢。我正在寻找让Quora变得更快的方法。

以下是前端的代码:

<script type="text/javascript">


var URL2 = '<?php e(SITE_URL); ?>fronts/searchKeywords';

jQuery(document).ready(function(){

var CityKeyword = jQuery('#CityKeyword');

CityKeyword.autocomplete({
minLength    : 1,
source        : URL2
});

});
 </script>

以下是服务器端的代码:

function searchKeywords(){

    if ($this->RequestHandler->isAjax() ) {
        $this->loadModel('Expertise_area');
        Configure::write ( 'debug',0);
        $this->autoRender=false;

        $expertise=$this->Expertise_area->find('all',array(
                'conditions'=>array('Expertise_area.autocomplete_text LIKE'=>'%'.$_GET['term'].'%'), 
                'fields' => array('DISTINCT (Expertise_area.autocomplete_text) AS autocomplete_text'),
                'limit'=>5
        ));
        $i=0;
        if(!empty($expertise)){
            $len = strlen($_GET['term']);
            foreach($expertise as $valueproductname){
                $pos = stripos($valueproductname['Expertise_area']['autocomplete_text'],$_GET['term']);
                $keyvalue = "";

                if($pos == 0) {
                    $keyvalue= "<strong>".substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
                            .substr($valueproductname['Expertise_area']['autocomplete_text'],$len);
                }else {
                    $keyvalue= substr($valueproductname['Expertise_area']['autocomplete_text'],0,$pos)."<strong>"
                            .substr($valueproductname['Expertise_area']['autocomplete_text'],$pos,$len)."</strong>"
                            .substr($valueproductname['Expertise_area']['autocomplete_text'],$pos+$len);
                }


                $response[$i]['value']=$valueproductname['Expertise_area']['autocomplete_text'];
                $response[$i]['label']="<span class=\"username\">".$keyvalue."</span>";
                $i++;

            }
            echo json_encode($response);
        }else{
        }
}
}

我已经研究了一下,到目前为止,以下解决方案值得一看:

  1. 查询页面加载数据并将其存储在COOKIE中以备将来使用。

  2. 实现一些缓存机制(memcache ??)。但我的网站是关于Cakephp的,如果我是对的,那就是内部cahcing。因此,向这个方向前进是值得的。

  3. 使用像Solr,Lucene等一些第三方索引机制。对此不太了解。

  4. 自己实施一个复杂的“前缀搜索”
  5. 正确的方法是什么?请帮帮我。

2 个答案:

答案 0 :(得分:1)

我从未尝试过这个,但很快就会为我正在进行的项目做这件事。

我一直认为在初始页面加载期间可能会收到一些AJAX(或者可能只是在页面中包含它)每个字母的前10个单词...例如

A - 苹果,anoraks,阿拉斯加,安吉拉,啊哈,空气,arrgh,任何,阿尔法,美国 B - 黄油,鲍勃等......

这样,当用户按下A-Z时,您可以立即为他们提供10个最受欢迎的关键字而无需任何进一步的请求,因为您已将它们存储在JS中的数组中。

我不确定尺寸/内存使用情况,但可以进一步扩展以处理前两个字母,例如AA,AB,AC ..... BA,BB,BC .... ZA,ZB,ZZ ......当然,许多组合,例如以ZZ开头的单词将不会有任何数据,除非它是一个音乐网站,它是ZZ顶级!这意味着在初始页面加载期间发送此数据可能不会占用太多内存或带宽。只有当用户键入第3个字母时,您才需要进行任何进一步的数据查找/传输。

您可以每天,每周或其他任何时间自动更新此数据,具体取决于网站使用情况和最常用的搜索结果。

答案 1 :(得分:0)

我正在为我的问题添加一个解决方案,经过大量研究后我发现了这个问题。

问题是:

  1. 每次用户更改搜索框中的文字时,我都会使用Ajax从数据库中获取关键字

  2. 我正在进行外卡搜索,以匹配整个字符串中的搜索项,而不仅仅是ex的关键字。 “dev”将回归“社会发展”,“发展”等

  3. 解决方案:

    1. 我有一组固定的关键字(200),不会在不久的将来呈指数级增长。因此,我目前正在发送数组中的所有关键字,而不是进行复杂的索引。

    2. 我在页面加载时将数据发送到数组中,因为它很小。如果它变大,我会通过不同索引数组中的一些ajax在后台获取它。

    3. 我正在使用jQuery的Autocomplete小部件来为我做其他事情。

    4. 为了突出搜索项目,我通过解决__renderItem来使用hack。 (从Stackoverflow复制。感谢!!)

    5. 代码:

      function monkeyPatchAutocomplete() { //Hack to color search item
      
      jQuery.ui.autocomplete.prototype._renderItem = function( ul, item) {
          var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + this.term + ")(?![^<>]*>)(?![^&;]+;)", "gi");
          var t = item.label.replace(re,"<span style='font-weight:bold;color:#434343;'>" + 
                  "$&" + 
                  "</span>");
          return jQuery( "<li></li>" )
              .data( "item.autocomplete", item )
              .append( "<a>" + t + "</a>" )
              .appendTo( ul );
      };
      }
      
      function getKeywords(){ 
      //Function that returns list of keywords. I am using an array since my data is small.
      //This function can be modified to fetch data in whatever way one want. 
      //I intend to use indexed arrays in future if my data becomes large.
      
          var allKeywords = <?php echo json_encode($allKeywords); ?>;
      
          return allKeywords;
      }
      
      jQuery(document).ready(function(){
      
      monkeyPatchAutocomplete();
      
      var CityKeyword = jQuery('#CityKeyword');
      
      CityKeyword.autocomplete({
      minLength    : 1,
      source        : getKeywords()
      });
      
      });