Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите написать нормальный запрос для поиска, по базе MySQL 
:(
    Опции темы
Borland_Delphi_6
Дата 3.2.2006, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



Уже замучался с попытками сделать нормальный поисковик для своего сайта. В оригинале используется такой запрос:
SQL
$sql = ldu_mysql_query("SELECT * FROM $db_news WHERE (news_title = '%$sqlsearch%' OR news_text = '%$sqlsearch%') AND news_minlevel<='".$usr['level']."' AND news_date<'".$sys['now_offset']."' ORDER by news_date ", "Plugin/simplesearch/news");


Но он выдает какие-то совершенно дикие результаты, что поиском назвать ну никак нельзя. Например, по запросу "Рома" выдает страницу со словом "романтика" ну и т.д. Если же убрать "%", то не выдает почти ничего. Возможно, кто-то уже пытался реализовать более "интеллектуальный" поиск и будет не жалко поделится? Ну или хоть советы какие-то дайте чтоли... smile

Стоит ли применять "полнотекстовый" поиск, если таблица не очень большая? Какие это даст преимущества/недостатки?


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
AntonioBanderaz
Дата 4.2.2006, 02:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Поищи доки про полнотекстовой поиск

Код

SELECT table.* 
             MATCH (table.<поле где искать>) 
             AGAINST ('что искать') AS score --Здесь будет на сколько твоя строка совподает с найденой
             FROM table 
                  WHERE MATCH (table.<поле где искать>)
                  AGAINST ('что искать')
             ORDER BY score




--------------------
ГЫ... 
PM MAIL ICQ   Вверх
-=Ustas=-
Дата 4.2.2006, 06:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 17
Всего: 69



Или LIKE заюзай.
String Comparison Functions
Full-Text Search Functions

Это сообщение отредактировал(а) -=Ustas=- - 4.2.2006, 06:34


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Borland_Delphi_6
Дата 4.2.2006, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



AntonioBanderaz
Я его уже реализовал, но нужно ли оно мне? Насколько снизится скорость?

-=Ustas=-

Тоже пробовал. как правило не слишком удачные результаты выдает.


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
AntonioBanderaz
Дата 5.2.2006, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Borland_Delphi_6 @ 4.2.2006, 16:24 Найти цитируемый пост)

Насколько снизится скорость?

Сам замерь... Я думаю не на много.
Добавлено @ 17:01
Цитата(Borland_Delphi_6 @ 4.2.2006, 16:24 Найти цитируемый пост)

нужно ли оно мне?

Это уже не мне решать ))))) Замерь и посмотри что по твоим критериям выдаст наиболее приемлимый результат...


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Borland_Delphi_6
Дата 9.2.2006, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



Блин, что-то я никак врубится не могу. Как мне с помощью LIKE сделать такую фигню: поиск ищет точное слово, но оно может встречатся в любом месте в тексте? Т.е. есть текст:

Цитата(Текст№1)

Это очень хороший, длинный и сочный текст, который содержет в себе много полезной информации. Прочитав его, вы узнаете много нового ни о чем, бла-бла-бла и тра-та-та.


Цитата(Текст№2)

Сок - это очень вкусно.


Мне нужно найти слово "сочный". Если сделать "%сочный%", то помимо страницы с текстом №1, выдаст также и страницу №2. Если сделать просто WHERE smth = 'сочный', то не найден ни того, ни другого smile Нужно, чтобы искал точное совпадение...


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
AntonioBanderaz
Дата 9.2.2006, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



RLIKE попробуй либо регульками в базе, а я бы сделал полнотекстовым!!!


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Borland_Delphi_6
Дата 9.2.2006, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



Вот что у меня получилось:

Код


//Разбиваем на логическое "ИЛИ" и обрабатываем запросы

$sqlsearch = "Some text to search";

        $logic_or = explode("^", $sqlsearch); 
        $logic_or_count = count($logic_or);
        if ($logic_or_count > 5)
                {
                $plugin_body .= "<p align=\"center\" style=\"color: red; font-weight: bold;\">Слишком много вложенных запросов логического \"ИЛИ\".<br />Максимально допустимое количество запросов - 4.</p>";
                $a = '';
                $continue_searching = 0;
                }

        //Создаем будущий SQL запрос
        if ($logic_or_count == 1) { $future_sql_query = "SELECT * FROM $db_news WHERE (news_title RLIKE '$logic_or[0]' OR news_text RLIKE '$logic_or[0]' OR news_title RLIKE '$logic_or[1]' OR news_text RLIKE '$logic_or[1]') AND news_minlevel<='".$usr['level']."' AND news_date<'".$sys['now_offset']."' ORDER by news_date "; }
        if ($logic_or_count == 2) { $future_sql_query = "SELECT * FROM $db_news WHERE (news_title RLIKE '$logic_or[0]' OR news_text RLIKE '$logic_or[0]' OR news_title RLIKE '$logic_or[1]' OR news_text RLIKE '$logic_or[1] OR news_title RLIKE '$logic_or[2]' OR news_text RLIKE '$logic_or[2]') AND news_minlevel<='".$usr['level']."' AND news_date<'".$sys['now_offset']."' ORDER by news_date "; }
        }
        //Создали... :)


Как видно, далеко не самый удачный вариант. Как бы эти длинные условия ("news_title RLIKE '$logic_or[0]' OR news_text RLIKE '$logic_or[0]' OR news_title RLIKE '$logic_or[1]' OR news_text RLIKE '$logic_or[1] OR news_title RLIKE '$logic_or[2]' OR news_text RLIKE '$logic_or[2]'") заменить регулярными выражениями? Насколько я понимаю, это ведь можно сделать?


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
-=Ustas=-
Дата 10.2.2006, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 17
Всего: 69



Borland_Delphi_6, тебе же уже советовали полнотекстовый поиск делать.... И выход этот правильный, т.к. через созданный индекс можно производить не физический, а логический поиск. Правда это если мускул не менее 4-ой версии.
Цитата

В MySQL 4.0.1 возможен полнотекстовый поиск также и в логическом режиме с использованием модификатора IN BOOLEAN.
Данный запрос вывел все строки, содержащие слово ``MySQL'' (заметьте, 50-процентная пороговая величина здесь не используется), но эти строки не содержат слова ``YourSQL''. Следует отметить, что логический режим поиска не сортирует автоматически строки в порядке уменьшения релевантности. Это видно по результату предыдущего запроса, где строка с наиболее высокой релевантностью (содержащая слово ``MySQL'' дважды) помещена последней, а не первой. Логический режим полнотекстового поиска может работать даже без индекса FULLTEXT, хотя и очень медленно.

В логическом режиме полнотекстового поиска поддерживаются следующие операторы:

+

Предшествующий слову знак ``плюс'' показывает, что это слово должно присутствовать в каждой возвращенной строке.

-

Предшествующий слову знак ``минус'' означает, что это слово не должно присутствовать в какой-либо возвращенной строке.

По умолчанию (если ни плюс, ни минус не указаны) данное слово является не обязательным, но содержащие его строки будут оцениваться более высоко. Это имитирует поведение команды MATCH() ... AGAINST() без модификатора IN BOOLEAN MODE.

< >

Эти два оператора используются для того, чтобы изменить вклад слова в величину релевантности, которое приписывается строке. Оператор < уменьшает этот вклад, а оператор > - увеличивает его. См. пример ниже.

( )

Круглые скобки группируют слова в подвыражения.

~

Предшествующий слову знак ``тильда'' воздействует как оператор отрицания, обуславливая негативный вклад данного слова в релевантность строки. Им отмечают нежелательные слова. Строка, содержащая такое слово, будет оценена ниже других, но не будет исключена совершенно, как в случае оператора - ``минус''.

*

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


И так далее, дальше можешь сам почитать smile http://dev.mysql.com/doc/refman/4.0/ru/fulltext-search.html

Это сообщение отредактировал(а) -=Ustas=- - 10.2.2006, 09:34


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Borland_Delphi_6
Дата 10.2.2006, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



-=Ustas=-
Да я пытаюсь, но полнотекстовый поиск не могу наладить для поля news_title, а для news_text все сделать удалось. Можно увидеть, какой запрос необходимо выяснить, чтобы разрешить полнотекстовый поиск для опр. поля?


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
-=Ustas=-
Дата 10.2.2006, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 17
Всего: 69



Borland_Delphi_6, тонкую настройку "Тонкая настройка полнотекстового поиска в MySQL" смотрел? Может тебе переменный надо настроить.


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Borland_Delphi_6
Дата 10.2.2006, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



-=Ustas=-
Мне честно говоря этот полнотекстовый поиск не очень симпатизирует, из-за того, что он сам решает, на какие слова реагировать, а на какие нет, а также из-за своей нагрузки на БД... Но попробую чего-нибудь сделать. Мой вопрос по поводу оптимизации запроса в силе. Если непонятно, что я пытался спросить - дайте знать smile


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
Borland_Delphi_6
Дата 10.2.2006, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


LoneLINEss
****


Профиль
Группа: Участник Клуба
Сообщений: 2509
Регистрация: 5.11.2002
Где: in fortune dreams ...

Репутация: нет
Всего: 20



Короче, делаю два запроса на создание индексов поиска:

Код

ALTER  TABLE  `ldu_news`  ADD  FULLTEXT (  `news_text`  );
ALTER  TABLE  `ldu_news`  ADD  FULLTEXT (  `news_title`  );


Индексы вроде создаются. Дальше пытаюсь искать таким вот запросом:

Код

$sql = ldu_mysql_query("SELECT *, MATCH (news_title,news_text) AGAINST
                ('$sqlsearch') AS score
                FROM $db_news WHERE MATCH (news_title,news_text) AGAINST
                ('$sqlsearch')");


И получаю ошибку:
Цитата

MySQL error : Can't find FULLTEXT index matching the column list


Причем если искать по одному полю, то все ок. В чем трабл?


--------------------
Blind Guardian Fan :: BMSTU Student :: A polar bear is a rectangular bear after a coordinate transform.

Мои фотографии
PM MAIL WWW   Вверх
AntonioBanderaz
Дата 10.2.2006, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Код

<?php    
/*    
Class MysqlSearch    
Anton Velichko 10.02.2006    
*/    
class MysqlSearch {    
    var $host = ''; //Сервер подключения Mysql    
    var $user = 'root'; //Пользователь    
    var $password = ''; //Пароль    
    var $database = ''; //База данных    
     
    var $__activeLink = '';    
    var $__connectKey = '';    
    var $__searchMass = array();    
     
    var $where = array(); //Массив типа таблица=>row    
    var $what = ''; //Строка поиска    
    var $resultMass = array();    
     
     
     
    function MysqlSearch($host = '',$user = '',$password = '',$database = '') {    
            $this->host = $host;    
            $this->user = $user;    
            $this->password = $password;    
            $this->database = $database;    
             
            $this->__connectKey = mysql_connect($this->host,$this->user,$this->password);     
            mysql_select_db($this->database,$this->__connectKey);    
    }    
     
    function newSearch($what,$where) {    
        if(is_array($where) && isset($what)) {     
            $this->what = $what;    
            $this->where = $where;    
            $this->splitWhat();    
            $this->createQuery();    
        }     
    }    
     
    function getResults() {    
        return $this->resultMass;    
    }    
     
    function createQuery() {    
        foreach($this->where as $key => $value) {    
            $query = "select * from $key where ";    
            for($i=0;$i<count($this->__searchMass);$i++) {    
              foreach($value as $val)
                $query.='( '.$val." rlike '".$this->__searchMass[$i]."' ) or ";    
            }    
            $query = substr($query,0,strlen($query)-4);    
            //echo $query;    
            $this->__activeLink = mysql_query($query,$this->__connectKey);    
            while($row = mysql_fetch_assoc($this->__activeLink)) array_push($this->resultMass,$row);    
        }    
             
    }    
     
    function splitWhat() {    
        $separators = " ,.!?-";    
        $wordArray = array();    
        $total = 0;    
        for($token = strtok($this->what,$separators);$token !== false;$token = strtok($separators)) {    
            if($token != "" ) {    
                if(!isset($word_count[strtolower($token)])) {    
                     $word_count[strtolower($token)] = 1;    
                     array_push($wordArray,strtolower($token));    
                }    
                else $word_count[strtolower($token)]++;    
                $total++;    
            }     
        }    
        for($i=0;$i<count($wordArray);$i++) {    
            $this->createResultMass($i,count($wordArray),$wordArray);    
        }    
    }    
     
    function createResultMass($start,$end,$mass) {    
        if($end > $start) {    
            $val = '';    
            for($i=$start;$i<$end;$i++) $val .= ' '.$mass[$i];     
            array_push($this->__searchMass,$val);    
            $this->createResultMass($start,$end-1,$mass);    
        }    
             
    }    
}    
/* Пример использования    
$search = new MysqlSearch('host','user','password','db');    
$search->newSearch('search string',array("table"=>"массив полей"));    
print_r($search->getResults());    
*/    
?>


Ну как-то так короче...
Добавлено @ 19:18
Код

ALTER  TABLE  `ldu_news`  ADD  FULLTEXT (  `news_text`, `news_title`  );

А так?


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
-=Ustas=-
Дата 11.2.2006, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 17
Всего: 69



Цитата(Borland_Delphi_6 @ 10.2.2006, 18:38 Найти цитируемый пост)
ALTER  TABLE  `ldu_news`  ADD  FULLTEXT (  `news_text`  );
ALTER  TABLE  `ldu_news`  ADD  FULLTEXT (  `news_title`  );

Цитата(Borland_Delphi_6 @ 10.2.2006, 18:38 Найти цитируемый пост)
Причем если искать по одному полю, то все ок. В чем трабл?

Это потому, что у тебя индексы созданы отдельно для каждого поля.


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0588 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.