2013-08-28 1 views
0

У меня есть база данных, содержащая список файлов (около 6000 файлов). Все эти файлы имеют определенные дополнительные сведения, связанные с ними (например, номера проектов, сектора, клиенты, комментарии, дисциплины).Оптимизация поискового кода - CakePHP

Хотя код и поиск работают, это очень медленно. Простой поиск с двумя терминами занимает около минуты.

Мой код ниже. Я хочу знать, что я могу сделать для упрощения и оптимизации моей функции поиска?

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 так понятия не имеют, что нужно сделать, чтобы улучшить его.

Любая помощь будет оценена по достоинству.

ответ

0

Чтобы сделать это быстрее, вы должны отложить как можно большую ответственность за базу данных (базы данных ДЕЙСТВИТЕЛЬНО быстро в эти дни!) И минимизировать время между PHP и базой данных. В идеале вы должны получать все результаты поиска в одном запросе (т. Е. Один вызов find).

Вы должны указать joins, чтобы ваша модель KmFile была присоединена слева к вашим таблицам KmClient, KmProject и т. Д.

Тогда это всего лишь вопрос создания длинного массива условий. В Cake, вы можете указать 'OR' условия, как это:

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

Отъезд DOCO на complex find conditions. Ваш массив условий будет выглядеть примерно так:

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-коде и рассчитать релевантность для каждого из них.

Смежные вопросы