похожие темы через sphinx
Дело, было как обычно вечером :) И лежало на мне уже давно задание — добавить «похожие темы» к проекту, но ввиду приоритетов откладывалось оно на потом постоянно. Полазил по LS, нашел уже готовый бесплатный модуль: livestreet.ru/blog/2053.html
Но незадача :( нужен fulltext для InnoDB… уже хотел похерить задание и отложить опять до лучших времен, но что-то дернуло меня все-таки покопаться чуток. А именно, вспомнил я про уже готовый fulltext поиск реализованный на sphinx'e в дефолтной сборке LS. Там как раз есть тайтл + текст, так что впринципе больше и не надо :)
В общем, пришлось чуток модифицировать имеющийся модуль + добавить ф-цию в Sphinx.class.php
К действиям:
1) берем имеющийся модуль
2) удаляем папку и ее содержимое /classes/modules/similartopics/mapper
3) заменяем полностью содержимое файла(/classes/modules/similartopics/SimilarTopics.class.php) на:
4) добавляем в класс(classes/modules/sphinx/Sphinx.class.php):
лично я оставил поиск по тэгам, хотя — можете добавить и по тайтлу, как было первоначально в плагине
5) все, радуемся жизни :)
п.с. должен быть настроен уже sphinx и работать поиск через sphinx
п.п.с. делаем на свой страх и риск, так что не забываем о том что надо бэкапить файлы ;)
Но незадача :( нужен fulltext для InnoDB… уже хотел похерить задание и отложить опять до лучших времен, но что-то дернуло меня все-таки покопаться чуток. А именно, вспомнил я про уже готовый fulltext поиск реализованный на sphinx'e в дефолтной сборке LS. Там как раз есть тайтл + текст, так что впринципе больше и не надо :)
В общем, пришлось чуток модифицировать имеющийся модуль + добавить ф-цию в Sphinx.class.php
К действиям:
1) берем имеющийся модуль
2) удаляем папку и ее содержимое /classes/modules/similartopics/mapper
3) заменяем полностью содержимое файла(/classes/modules/similartopics/SimilarTopics.class.php) на:
<?php ##### [hack] similar_topics_sphinx ##### class LsSimilarTopics extends Module { public function Init() { } public function GetSimilarTopics($oTopic){ $sTitleTags=$oTopic->getTags(); $aTopics=array(); $data=$this->Sphinx_FindSimilarTopics($sTitleTags,SIMILARTOPICS_COUNT+1); if(is_array($data['matches']) && sizeof($data['matches'])>0){ foreach($data['matches'] as $k=>$v) if($k!=$oTopic->getId()) $aTopics[]=$this->Topic_GetTopicById($k); return $aTopics; }else return false; } } ##### [hack] similar_topics_sphinx ##### ?>
4) добавляем в класс(classes/modules/sphinx/Sphinx.class.php):
##### [hack] SimilarTopics ##### public function FindSimilarTopics($sTerms,$iLimit){ $cacheKey=SEARCH_ENTITY_PREFIX."similartopics_{$sTerms}_{$iLimit}"; if(false===($data=$this->Cache_Get($cacheKey))){ $this->oSphinx->SetMatchMode(SPH_MATCH_ANY); $this->oSphinx->SetLimits(0,$iLimit); if(!is_array($data=$this->oSphinx->Query($sTerms,SEARCH_ENTITY_PREFIX.'topicsIndex'))) return FALSE; # no results = no cache if($data['total']>0) $this->Cache_Set($data,$cacheKey,array(),60*15); } return $data; } ##### [hack] SimilarTopics #####
лично я оставил поиск по тэгам, хотя — можете добавить и по тайтлу, как было первоначально в плагине
5) все, радуемся жизни :)
п.с. должен быть настроен уже sphinx и работать поиск через sphinx
п.п.с. делаем на свой страх и риск, так что не забываем о том что надо бэкапить файлы ;)
Еще со времен СССР у российских женщин устойчивым спросом пользовалась профессиональная косметика из Франции. С приходом в нашу жизнь новых технологий делать покупки стало проще. Последние коллекции легендарной французской косметики вы можете приобрести тут.
29 комментариев
Тест сегодня неминуем.
Спасибо вам огромное!
короче, если вы брали код, то просьба его обновить — файл /classes/modules/similartopics/SimilarTopics.class.php
И вдвойне — за безвозмездность :)
Попутный вопрос — можно ли сделать, чтобы блок «похожих тем» отображался справа, но только при выводе самого топика?
При создании топика с несуществующими ранее данными вылезает парочка ошибок:
Т.е. видимо когда нечего подставлять в блок «Похожие топики», они и появляются.
посмотрите выше в главном посте пункт №3
Попробовал прикрутить с исправлениями, ошибок стало меньше :)
Наверху ошибка — Notice: Undefined index: matches in /home/webmaster/www/test.site/classes/modules/similartopics/SimilarTopics.class.php on line 10
На месте где сам блок вставлен:
Fatal error: Call to a member function getUrl() on a non-object in /home/webmaster/www/test.site/templates/compiled/%%27^27A^27A2FB40%%topic.tpl.php on line 134
Я еще раз попробую сделать все по новому с утра. Может что то напутал, шанс есть и не маленький.
Доброй ночи
Такая же ошибка. Есть решение?
А как это сделать? Что-то не догоняю никак…
Ну тогда хотелось бы добавить следущее: необходимо добавить поиск только по опубликованным топикам.
в SimilarTopics.class.php
в Sphinx.class.php
Слегка поясню что же я сделал:
1) Ищется теперь только в опубликованных
2) Усложнён запрос, теперь он формулируется так:
Теперь теги ищются среди тегов, а заголовок в заголовках и текстах, причём совпадения в тегах по двум словам, а в заголовке должны совпасть 60% слов.
P.S. Конечно в конфигурациях сфинкса (там где вы писали запросы к БД) нужно в запрос к топикам добавить поле topic_tags
Написал просто ппц как, но мне простительно, см. время коммента. Надеюсь кто нить разберётся в этом ночном бреде
Куда копать? Или мб кто знает аналог функции по подсчёту слов в строке?
class LsSimilarTopics extends Module {
public function Init() {
}
public function GetSimilarTopics($oTopic){
$iNumTitle = 0;
foreach (array_unique(preg_split('/[\s,]+/',$oTopic->getTitle())) as $var)
{
if (mb_strlen($var,'UTF-8')>1 and $var!='—') $iNumTitle++;
}
$iNumTags = 0;
foreach (array_unique(preg_split('/[\s,]+/',$oTopic->getTags())) as $var)
{
if (mb_strlen($var,'UTF-8')>1 and $var!='—') $iNumTags++;
}
$iNumTags = count(array_unique(preg_split('/[\s,]+/',$oTopic->getTags())));
$iNumTags = ($iNumTags > Config::Get('module.similartopics.num_tags')-1 )? Config::Get('module.similartopics.num_tags'): $iNumTags;
$sTitleTags='@topic_tags "'.$oTopic->getTags().'"/'.$iNumTags.' @(topic_title,topic_text) "'.$oTopic->getTitle().'"/'.round($iNumTitle*Config::Get('module.similartopics.percent_title'));
$aTopics=array();
if($data=$this->Sphinx_FindSimilarTopics($sTitleTags,Config::Get('module.similartopics.count')+1,array('topic_publish' => 1))){
foreach($data['matches'] as $k=>$v){
$obj=$this->Topic_GetTopicById($k);
if($k!=$oTopic->getId() && isset($obj)) $aTopics[]=$obj;
}
}
return $aTopics;
}
}
в конфиг similartopics внести строчки
$config['num_tags'] = 2; // какое количество тегов должно совпадать с тегами других топиков, что бы другие топики были «похожим»
$config['percent_title'] = 0.6; // процент количества всех слов из заголовка, которые должны совпасть с заголовками и текстами других топиков, чтобы именоваться похожими
Мб проверка на тире лишняя. Я повторных тестов не делал, поэтому решил оставить, время выполнения скрипта от неё не возрастёт.
Забыл уточнить… это всё работает для последних SVN. Не для 0.3.1
спасибо за дополненения, наверное обновлю плагин до ваших дополнений
После внесения изменений из комментариев от 21 ноября, возникла проблема с конструкцией Config::Get();.
Модификацию применяю на стабильный LiveStreet 0.3.1
Следует понимать, что доступ к конфигам через объект Config работает только с SVN-версией, или у меня то-то глючит? :)
Когда определил в конфиге константы и заменил Config::Get() на прямое их использование, то мод вроде как заработал, по крайней мере перестал выдавать ошибку об объекте Config.
Я же вроде говорил об этом… Будет ли работать на 0.3.1 не знаю… На последних свн будет.