Перейти к контенту

Полнотекстовый поиск


Рекомендуемые сообщения

С ростом журналов поиск стал сильной проблемой, особенно в комментах.

Два-три поиска, запущенных одновременно убивали MySQL.

Ограничивал число результатов поиска пока поиск в коментах вообще не выключил, что есть очень плохо.

 

Озаботился полнотесктовым, вроде не нашёл упоминаний, чтобы это кто-то делал.

 

Попробовал сам, но не уверен, что всё сделал корректно.

 

Что сделал?

 

/journal/misc/user_search.php

1. закомментировал:

			$DB->query("SELECT p.pid FROM ibf_jposts p WHERE p.journal_id='".$journal->users['id']."' AND (".$search['SEARCH'].")".$q_extra." LIMIT 1000");

после вставил:

			$DB->query("SELECT p.pid FROM ibf_jposts p WHERE MATCH (post, title) AGAINST ('".$search['SEARCH']."' IN BOOLEAN MODE) AND p.journal_id='".$journal->users['id']."' ".$q_extra." LIMIT 1000");

 

2. закомментировал:

			$DB->query("SELECT cid
					FROM ibf_jcomments c
					LEFT JOIN ibf_jposts p ON (p.pid=c.post_id)
					LEFT JOIN ibf_jmembers m ON (m.id=c.owner_id)
					WHERE c.owner_id = '".$journal->users['id']."' AND (".$search['SEARCH'].")".$q_extra." LIMIT 1000");

после вставил:

			$DB->query("SELECT cid
					FROM ibf_jcomments c
					LEFT JOIN ibf_jposts p ON (p.pid=c.post_id)
					LEFT JOIN ibf_jmembers m ON (m.id=c.owner_id)
					WHERE c.owner_id = '".$journal->users['id']."' AND MATCH (c.post) AGAINST ('".$search['SEARCH']."' IN BOOLEAN MODE)".$q_extra." LIMIT 1000");

 

3. закомментировал:

	function make_search_text($q = "LCASE(p.post)")
{
	global $ibforums;

	$name = strtolower(trim(urldecode($ibforums->input['name'])));
	$name = str_replace("&","&",$name);
	$name = preg_replace( "/\&\#[0-9]+;|<br \/>|\&(gt|lt|quot|amp);/i", "", $name );
	$name = preg_replace( "/[^a-zA-Z0-9р- └-▀\|\&\s]/", "", $name );

	$name = preg_replace( "/^(?:img|quote|code|html|javascript|a href|color|span|div|border|style|class)$/", "", $name );

	// add space if not set with |,& (word&word must be word & word)
	$name = preg_replace("/([\&\|])(\S+?)/","\\1 \\2",$name);
	$name = preg_replace("/(\S+?)([\&\|])/","\\1 \\2",$name);

	// remove smaller word ( <4 )
	$name = preg_replace("/(^|[\|\&\s]+)\S{1,3}([\|\&\s]+|$)/","\\2",$name);

	// remove first |,&
	$name = preg_replace("/^([\|\&\s]+)/","",$name);

	// remove last |,&
	$name = preg_replace("/([\|\&\s]+)$/","",$name);

	// remove double |,&
	$name = preg_replace("/(\s[\&\|]){2,}/","\\1",$name);

	$search_name = array('ORIGINAL' => $name,
						 'SEARCH'   => '',
						 'HLITE'	=> array());

	$name = explode(" ",$name);
	$next_sep = "";

	foreach ($name as $val)
	{
		if ($val == "")
		{
			continue;
		}

		if ($val == '|')
		{
			$next_sep = 'OR';
		}
		else if ($val == '&')
		{
			$next_sep = 'AND';
		}
		else
		{
			if ($search_name['SEARCH'] != "") $search_name['SEARCH'] .= $next_sep." ";
			$search_name['SEARCH'] .= $q." LIKE '%".trim($val)."%' ";
			$next_sep = 'AND';
			$search_name['HLITE'][] = trim($val);
		}
	}

	// remove unused :)
	$search_name['SEARCH'] = preg_replace("/[\|\&]/","",$search_name['SEARCH']);

	return $search_name;
}

после вставил:

	function make_search_text($q = "LCASE(p.post)")
{
	global $ibforums;

// force to lowercase and swop % into a safer version

	$words = trim( rawurldecode($ibforums->input['name']) );
	$words = str_replace( '|', "|", $words );

	// Remove crap

	$words = str_replace( """, '"', $words );
	$words = str_replace( ">"  , ">", $words );
	$words = str_replace( "%"	 , "" , $words );

	//-----------------------------------------
	// If it's a phrase in quotes..
	//-----------------------------------------

	if ( preg_match( "#^\"(.+?)\"$#", $words ) )
	{
		return $words;
	}

	// Remove common words..

	$words = preg_replace( "/^(?:img|quote|code|html|javascript|a href|color|span|div|border|style)$/", "", $words );

	// OK, lets break up the keywords

	// this or that and this not me

	$words = preg_replace( "/\s+and\s+/i", " ", $words );

	// this or that this not me

	$words = preg_replace( "/\s+not\s+/i", " -", $words );

	// this or that this -me

	$words = preg_replace( "/\s+or\s+/i", ' ~', $words );

	// this ~that this -me

	# Was added as a bug fix but really this causes more problems
	# than it solves. Complaint was that it should default to AND
	# matching, not OR matching. Problem is that it doesn't then
	# give a "true" search as one would expect Google to do.

	//$words = preg_replace( "/\s+(?!-|~)/", " +", $words );


	// this ~that +this -me

	$name = str_replace( "~", "", $words );


$search_name = array('ORIGINAL' => $name,
						 'SEARCH'   => '+'.$name,
						 'HLITE'	=> array());

	$name = explode(" ",$name);

	foreach ($name as $val)
	{
		if (($val == "") or ($val == '*')  or ($val == '+') or ($val == '-') or ($val == '~')) 
		{
			continue;
		}

		$search_name['HLITE'][] = trim($val);
	}

	return $search_name;
}

 

/journal/misc/main_search.php

4. закомментировал:

			$DB->query("SELECT p.pid
					FROM ibf_jposts p
					LEFT JOIN ibf_jmembers m ON (m.id=p.journal_id)
					WHERE (".$search['SEARCH'].")".$q_extra." LIMIT 1000");

после вставил:

			$DB->query("SELECT p.pid
					FROM ibf_jposts p
					LEFT JOIN ibf_jmembers m ON (m.id=p.journal_id)
					WHERE MATCH (post, title) AGAINST ('".$search['SEARCH']."' IN BOOLEAN MODE) ".$q_extra." LIMIT 1000");

 

5. закомментировал:

			$DB->query("SELECT cid
					FROM ibf_jcomments c
					LEFT JOIN ibf_jposts p ON (p.pid=c.post_id)
					LEFT JOIN ibf_jmembers m ON (m.id=p.journal_id)
					WHERE (".$search['SEARCH'].")".$q_extra." LIMIT 1000");

после вставил:

			$DB->query("SELECT cid
					FROM ibf_jcomments c
					LEFT JOIN ibf_jposts p ON (p.pid=c.post_id)
					LEFT JOIN ibf_jmembers m ON (m.id=p.journal_id)
					WHERE MATCH (c.post) AGAINST ('".$search['SEARCH']."' IN BOOLEAN MODE) ".$q_extra." LIMIT 1000");

 

6. закомментировал:

	function make_search_text($q = "LCASE(p.post)")
{
	global $ibforums;

	$name = strtolower(trim(urldecode($ibforums->input['name'])));
	$name = str_replace("&","&",$name);
	$name = preg_replace( "/\&\#[0-9]+;|<br \/>|\&(gt|lt|quot|amp);/i", "", $name );
	$name = preg_replace( "/[^a-zA-Z0-9р- └-▀\|\&\s]/", "", $name );

	$name = preg_replace( "/^(?:img|quote|code|html|javascript|a href|color|span|div|border|style|class)$/", "", $name );

	// add space if not set with |,& (word&word must be word & word)
	$name = preg_replace("/([\&\|])(\S+?)/","\\1 \\2",$name);
	$name = preg_replace("/(\S+?)([\&\|])/","\\1 \\2",$name);

	// remove smaller word ( <4 )
	$name = preg_replace("/(^|[\|\&\s]+)\S{1,3}([\|\&\s]+|$)/","\\2",$name);

	// remove first |,&
	$name = preg_replace("/^([\|\&\s]+)/","",$name);

	// remove last |,&
	$name = preg_replace("/([\|\&\s]+)$/","",$name);

	// remove double |,&
	$name = preg_replace("/(\s[\&\|]){2,}/","\\1",$name);

	$search_name = array('ORIGINAL' => $name,
						 'SEARCH'   => '',
						 'HLITE'	=> array());

	$name = explode(" ",$name);
	$next_sep = "";

	foreach ($name as $val)
	{
		if ($val == "")
		{
			continue;
		}

		if ($val == '|')
		{
			$next_sep = 'OR';
		}
		else if ($val == '&')
		{
			$next_sep = 'AND';
		}
		else
		{
			if ($search_name['SEARCH'] != "") $search_name['SEARCH'] .= $next_sep." ";
			$search_name['SEARCH'] .= $q." LIKE '%".trim($val)."%' ";
			$next_sep = 'AND';
			$search_name['HLITE'][] = trim($val);
		}
	}

	// remove unused :)
	$search_name['SEARCH'] = preg_replace("/[\|\&]/","",$search_name['SEARCH']);

	return $search_name;
}

после вставил:

	function make_search_text($q = "LCASE(p.post)")
{
	global $ibforums;

// force to lowercase and swop % into a safer version

	$words = trim( rawurldecode($ibforums->input['name']) );
	$words = str_replace( '|', "|", $words );

	// Remove crap

	$words = str_replace( """, '"', $words );
	$words = str_replace( ">"  , ">", $words );
	$words = str_replace( "%"	 , "" , $words );

	//-----------------------------------------
	// If it's a phrase in quotes..
	//-----------------------------------------

	if ( preg_match( "#^\"(.+?)\"$#", $words ) )
	{
		return $words;
	}

	// Remove common words..

	$words = preg_replace( "/^(?:img|quote|code|html|javascript|a href|color|span|div|border|style)$/", "", $words );

	// OK, lets break up the keywords

	// this or that and this not me

	$words = preg_replace( "/\s+and\s+/i", " ", $words );

	// this or that this not me

	$words = preg_replace( "/\s+not\s+/i", " -", $words );

	// this or that this -me

	$words = preg_replace( "/\s+or\s+/i", ' ~', $words );

	// this ~that this -me

	# Was added as a bug fix but really this causes more problems
	# than it solves. Complaint was that it should default to AND
	# matching, not OR matching. Problem is that it doesn't then
	# give a "true" search as one would expect Google to do.

	//$words = preg_replace( "/\s+(?!-|~)/", " +", $words );


	// this ~that +this -me

	$name = str_replace( "~", "", $words );


$search_name = array('ORIGINAL' => $name,
						 'SEARCH'   => '+'.$name,
						 'HLITE'	=> array());

	$name = explode(" ",$name);

	foreach ($name as $val)
	{
		if (($val == "") or ($val == '*')  or ($val == '+') or ($val == '-') or ($val == '~')) 
		{
			continue;
		}

		$search_name['HLITE'][] = trim($val);
	}

	return $search_name;
}

 

/cache/lang_cache/ru/lang_journal.php

7. нашёл

'j_s_rules_text'	=> "<b>Поиск по интересам, антиресам и нику пользователя</b><br />При поиске в интересах и антиресах все символы кроме букв, цифр и символов * и ? игнорируются.<br />При поиске разрешено использовать общепринятые сокращения (* и ?).<br /><br />При поиске дневника по нику можно использовать любые символы, однако символы * и ? будут восприняты как сокращения.<br /><br />Например: <b>игр*</b><br /> - найдет все слова начинающиеся на <b>игр</b> (игра, игроки, игрушки и т.д.).<br /><br />Например: <b>игр?</b><br /> - найдет слова 'игра', 'игры' и т.д., но не найдет слова 'игроки' и 'игрушки'.<br /><br />Например: <b>игр</b><br /> - найдет только слово 'игр'.<br /><br /><br />
					<b>Поиск по записям и комментариям</b><br />При поиске все символы кроме букв, цифр, символов & и | , а так же слова состоящие меньше чем из 4 букв игнорируются.<br />Запрещено использовать символы сокращений (* и ?).<br /> При поиске будут найдены все слова включающие в себя заданные при поиске части слов.<br /><br />Например: <b>игра</b><br /> - найдет слова 'игра', 'поиграть', 'играют' и проч.<br /><br />При поиске допустимо указывать несколько слов и использовать логические операторы. <br />Допустимы следующие операторы:<br />   <b>&</b> - логическое И<br />   <b>|</b> - логическое ИЛИ.<br /><br />
					Например: <b>игра & компьютер</b> - найдет все записи содержащие одновременно слово 'игра' и слово 'компьютер'<br /><br />Например: <b>игра | компьютер</b> - найдет все записи содержащие либо слово 'игра', либо слово 'компьютер'<br /><br />Если между словами не указан ни один из операторов, то по умолчанию используется оператор <b>&</b><br /><br />
					Например: <b>игра компьютер</b> - равнозначно указанию <b>игра & компьютер</b><br /><br />",

заменил на:

'j_s_rules_text'	=> "<b>Поиск по интересам, антиресам и нику пользователя</b><br />При поиске в интересах и антиресах все символы кроме букв, цифр и символов * и ? игнорируются.<br />При поиске разрешено использовать общепринятые сокращения (* и ?).<br /><br />При поиске журнала по нику можно использовать любые символы, однако символы * и ? будут восприняты как сокращения.<br /><br />Например: <b>игр*</b><br /> - найдет все слова начинающиеся на <b>игр</b> (игра, игроки, игрушки и т.д.).<br /><br />Например: <b>игр?</b><br /> - найдет слова 'игра', 'игры' и т.д., но не найдет слова 'игроки' и 'игрушки'.<br /><br />Например: <b>игр</b><br /> - найдет только слово 'игр'.<br /><br /><br />
					<b>Поиск по записям и комментариям</b><br />яблоко банан -  Поиск сообщений, содержащих одно из этих слов<br />
+яблоко +сок ===> Поиск сообщений, содержащих оба этих слова<br />
+яблоко -сок ===> Поиск сообщений, содержащих слово 'яблоко' и не содержащих слова 'сок'<br />
ябло* ===> Поиск сообщений, содержащих слово 'яблоко' и/или 'яблочный'<br />
\"Некоторые слова\" ===> Поиск сообщений, содержащих фразы 'некоторые слова являются мудрыми', 'некоторые слова' и не содержащих фразу 'некоторые нецензурные слова'<br /><br />",

 

 

8. SQL

ALTER TABLE `ibf_jposts`  ENGINE = MYISAM;

ALTER TABLE `ibf_jposts` ADD FULLTEXT (
`post` ,
`title`
);

ALTER TABLE `ibf_jcomments`  ENGINE = MYISAM;

ALTER TABLE `ibf_jcomments` ADD FULLTEXT (
`post`
);

 

 

Тем, кто не понимает, что происходит, крайне не советую производить эти изменения.

На моём форуме вроде всё работает, но....

В общем тем кто разбирается просьба оценить и совместно довести до ума.

Ссылка на комментарий
Поделиться на других сайтах

Присоединиться к обсуждению

Вы можете ответить сейчас, а зарегистрироваться позже. Если у вас уже есть аккаунт, войдите, чтобы ответить от своего имени.

Гость
Ответить в этой теме...

×   Вы вставили отформатированный текст.   Удалить форматирование

  Допустимо не более 75 смайлов.

×   Ваша ссылка была автоматически заменена на медиа-контент.   Отображать как ссылку

×   Ваши публикации восстановлены.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Зарузка...
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, вы соглашаетесь на использование файлов cookie, а также с нашим положением о конфиденциальности Политика конфиденциальности и пользовательским соглашением Условия использования.