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

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


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

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

Два-три поиска, запущенных одновременно убивали 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`
);

 

 

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

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

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

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

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

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

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

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

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

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

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