0

我有一个包含文件列表(大约 6000 个文件)的数据库。所有这些文件都有与之相关的某些附加详细信息(例如项目编号、部门、客户、评论、学科)。

尽管代码和搜索有效,但速度很慢。包含两个词的简单搜索大约需要一分钟才能完成。

我的代码如下。我想知道的是,我可以做些什么来简化和优化我的搜索功能?

public function search() {
    $Terms = explode(' ',$this->request->data['KmFiles']['search']);
    $possible = 0;
    $Matches = array();
    foreach($Terms as $Term) {
        $Files = $this->KmFile->find('list',
            array(
                'conditions' => array(
                    'file_name LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('id')
            )
        );
        $possible++;
        $Clients = $this->KmClient->find('list',
            array(
                'conditions' => array(
                    'clients LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('km_file_id')
            )
        );
        $possible++;
        $Disciplines = $this->KmDiscipline->find('list',
            array(
                'conditions' => array(
                    'disciplines LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('km_file_id')
            )
        );
        $possible++;
        $Projects = $this->KmProject->find('list',
            array(
                'conditions' => array(
                    'projects LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('km_file_id')
            )
        );
        $possible++;
        $Sectors = $this->KmSector->find('list',
            array(
                'conditions' => array(
                    'sectors LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('km_file_id')
            )
        );
        $possible++;
        $Comments = $this->KmComment->find('list',
            array(
                'conditions' => array(
                    'comments LIKE' => '%' . $Term . '%'
                ),
                'fields' => array('km_file_id')
            )
        );
        $possible++;
        $Matches = array_merge($Matches,$Files,$Clients,$Disciplines,$Projects,$Sectors,$Comments);
    }
    if(count($Matches) > 0) {
        $NumberOfMatches = array_count_values($Matches);
        $Matches = array_unique($Matches);
        $k=0;
        foreach($Matches as $Match) {
            $Result = $this->KmFile->find('all',
                array(
                    'conditions' => array(
                        'id' => $Match
                    )
                )
            );
        $Results[$k] = $Result[0];
        $Results[$k]['Relevance'] = round(($NumberOfMatches[$Match] / $possible) * 100,2);
        $relevance[] = $Results[$k]['Relevance'];
        $k++;
    }
        array_multisort($relevance,SORT_DESC,$Results);
        $Stats['Count'] = count($Results);
        $Stats['Terms'] = $this->request->data['KmFiles']['search'];
        $this->set(compact('Results','Stats'));
    } else {
        $Stats['Count'] = 0;
        $Stats['Terms'] = $this->request->data['KmFiles']['search'];
        $this->set(compact('Stats'));
    }
}

我知道这是一段很长的代码,但我对 CakePHP 还很陌生,所以不知道如何改进它。

任何帮助将不胜感激。

4

1 回答 1

0

为了让它更快,你必须尽可能多地把责任交给数据库(现在数据库真的很快!)并尽量减少 PHP 和数据库之间的来回。理想情况下,您会在单个查询(即单个find调用)中获取所有搜索结果。

您将指定joins,以便您的 KmFile 模型左连接到您的 KmClient、KmProject 等表。

然后,只需构建一个长条件数组即可。在 Cake 中,您可以像这样指定“或”条件:

array('OR' => array(
    array('Post.title LIKE' => '%one%'),
    array('Post.title LIKE' => '%two%')
))

查看有关复杂查找条件的文档。您的条件数组看起来像:

array('OR' => array(
    array('KmFile.file_name LIKE' => '%term1%'),
    array('KmFile.file_name LIKE' => '%term2%'),
    array('KmDiscipline.disciplines LIKE' => '%term1%'),
    array('KmDiscipline.disciplines LIKE' => '%term2%'),
    array('KmProject.projects LIKE' => '%term1%'),
    array('KmProject.projects LIKE' => '%term2%'),
    // and so on...
))

显然,您希望使用循环来构建您的条件数组。

然后在您的 KmFile 模型上进行一次查找,该模型与您的所有相关模型以及您的大条件列表相结合。这将返回一个匹配列表,并且不应该花费太长时间。

尽管我不知道如何计算,但可能可以在同一个查询中计算某种相关性分数。在任何情况下,一旦您在单个查询中获得您的查找结果,在 PHP 代码中循环遍历它们并计算每个查询的相关性应该不会花费太长时间。

于 2013-08-30T13:23:38.267 回答