【问题标题】:How to make search autocomplete faster?如何使搜索自动完成更快?
【发布时间】:2013-08-15 05:41:17
【问题描述】:

我已经使用 jQuery 自动完成功能实现了一个基本的自动完成功能。我每次都在查询数据库,这使得自动完成的事情变得很慢。我正在寻找使它更快的方法,就像 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. 自己实现一个非常复杂的“前缀搜索”

什么是正确的方法?请帮帮我。

【问题讨论】:

  • 在 DOM 加载时将所有可能的结果加载到一个变量中。不要使用 ajax。
  • @Ohgodwhy 我正在考虑这样做.. 但是将这些关键字存储在某处而不是每次都加载不是明智之举吗?如果是,那么最好的方法是什么? Cookie 还是会话?
  • CakePHP 以非常慢着称。它可以完成这项工作,但是如果您希望它非常快,那么您必须忘记框架并手动编写它。这不是很困难:创建一个PHP文件,打开一个db连接,搜索关键字并输出它。完毕。使用内存数据存储(如 memcache)可能会加快一些速度,但如果您的数据库设置正确,它应该能够处理它(例如,如果您使用索引并避免通配符搜索,MySQL 会非常快)。
  • @verri M. Olsen 如果我必须在字符串中显示任何匹配项而不仅仅是开始字符,那么有什么替代通配符搜索的方法?如何为它们生成索引?例如,如果用户输入“dev”,那么我必须显示“development”、“web development”、“social development”等。这让我的查询变慢了。

标签: php jquery caching autocomplete memcached


【解决方案1】:

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

我一直考虑在初始页面加载期间接收一些 AJAX(或者可能只是将其包含在页面中)每个字母的前 10 个单词的可能性。例如

A - apples, anoraks, alaska, angela, aha, air, arrgh, any, alpha, america B - 黄油、鲍勃等.....

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

我不确定大小/内存使用情况,但这可以进一步扩展以处理前 2 个字母,例如AA, AB, AC.....BA, BB, BC.... ZA, ZB, ZZ.... ZZ顶!这意味着在初始页面加载期间发送此数据可能不会占用太多内存或带宽。只有当用户键入第三个字母时,您才需要进行任何进一步的数据查找/传输。

您会根据网站使用情况和最热门的搜索,每天、每周或其他任何时间自动更新此数据。

【讨论】:

  • 问题是我必须显示所有包含用户输入的结果。例如,如果用户输入“dev”,那么我必须显示“development”、“web development”、“social development”等。这让我的查询变慢了。
  • 那么你不能用这个做一些类似于我的想法的事情吗?该值是在用户搜索结果之前预先计算的结果。没有理由不能在初始页面中将 'dev' = ['web development', 'social development'] 作为搜索的数组。只有你知道你的数据,显然发送 1MB 的 Javascript 会很愚蠢,但如果你轻松处理 95% 的情况,其他 5% 的等待时间会更长,但总体上会更快,因为数据库会更少由于 95% 没有使用它,所以使用过。
【解决方案2】:

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

问题是:

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

  2. 我正在执行通配符搜索以匹配整个字符串中的搜索项,而不仅仅是 ex 关键字的开头。 “dev”将返回“社会发展”、“发展”等

解决方案:

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

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

  3. 我正在使用 jQuery 的自动完成小部件为我完成其余的事情。

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

代码:

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()
});

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 2012-01-14
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2016-06-02
    相关资源
    最近更新 更多