Поиск в БД по подстрокам, не fulltext!

Discussion in 'PHP' started by Apeckou, 7 Jul 2012.

  1. Apeckou

    Apeckou Elder - Старейшина

    Joined:
    23 Jan 2007
    Messages:
    143
    Likes Received:
    11
    Reputations:
    0
    Плз помогите мне написать нормальный алгоритм поиска по базе, а то совсем уже все мозги себе нафик сломал.

    Требования:
    1. очень желательно сделать на MysqlI через bind_param (привык ему доверять в плане защищенности от инжектов)
    2. чтобы можно было вбивать несколько ОТРЫВКОВ слов через пробел, и каждое новое слово УТОЧНЯЛО поиск (т.е. поиск чтобы были все слова)

    3. вот тут хитро...
    В таблице FILES для каждого файла всегда указан автор файла в переменной WHO.
    Есть таблица PEOPLE, в ней настройки юзеров. В этих настройках есть поле PUBLIC.
    Нужно исключить из поиска те файлы, у чьих авторов параметр PUBLIC не равен 1...

    По отдельности все это сделать легко. А вот все вместе, с объединением таблиц...у меня мозг взорвался...
    Пока что сделал адски-варварски и без проверки 3 пункта... можете кидаться камнями, выкладываю код:

    PHP:

    //собственно наш запрос
    $wordstr=$_GET['wordstr'];
    $wordstr=lowerCase($wordstr);

    //обрезаем длину запроса и убираем из него всякую ересь
    $wordstr=substr($wordstr,0,100);
    while(
    strpos($wordstr,'  ')!==false){$wordstr=str_replace('  ',' ',$wordstr);}
    while(
    strpos($wordstr,'%%')!==false){$wordstr=str_replace('%%','%',$wordstr);}

    //коннектимся к базе
    $link=mysqli_connect("$myserver","$sqllogin","$sqlpass","$sqlbase");

    //вводим начало строки-запроса. Один для подсчета кол-ва всех файлов (понадобится), второй - собственно поиск по базе
    $string1="SELECT COUNT(*) FROM FILES WHERE status!='deleted'";
    $string2="SELECT name,size,author FROM FILES WHERE status!='deleted'";

    //начинаем колдовство...для каждого ключевого слова - дополняем запрос в мускул...пипец конечно
    foreach($words as $word)                 {

    $word=$link->real_escape_string($word);

    $string1.=" AND (LOWER(name) LIKE '%$word%' OR LOWER(text) LIKE '%$word%')";
    $string2.=" AND (LOWER(name) LIKE '%$word%' OR LOWER(text) LIKE '%$word%')";
                                        }

    //отправляем запрос на количество
    $stmt=$link->prepare("$string1");
    $stmt->bind_result($totfiles);
    $stmt->execute();
    $stmt->fetch();
    $stmt->close();

    //отправляем запрос на файлы
    $stmt=$link->prepare("$string2");
    $stmt->bind_result($name,$size,$author);
    $stmt->execute();



    while(
    $info=$stmt->fetch())                                        {
    .............
    тут уже вывод файлов
                                                        
    }

    Советовали всякие FULLTEXT, Sphinx и прочее... Ковырялся давно, но насколько помню, там нет возможности искать ПОДСТРОКИ (типа как like %abc%)
    Жду помощи...глаза вылезают...ололо(
     
    #1 Apeckou, 7 Jul 2012
    Last edited: 7 Jul 2012
  2. Art!P

    Art!P Elder - Старейшина

    Joined:
    22 Jan 2008
    Messages:
    169
    Likes Received:
    28
    Reputations:
    5
    не могу посоветовать что-то стоящее кроме как поменять стратегию и усложнить схему. Нужна таблица ключевых индексов, где будут слова от 3-х символов (без мусорных слов, или фильтр). Отдельный скрипт сканирует данные (страницы сайта, таблицы БД), закидывает в таблицу.
    В новой таблице каждое слово будет иметь ссылки (вхождение, количество).
    В самом поиске каждое слово ищется отдельно, фильтруется те кто не попадает по словам, ранжируется уже по кол-ву вхождения.
    Короче обычный поисковый индекс. Так устроен поиск у всех CMS.
    Эта таблица самая большая и составляет в кмсах 60-90% от общего объема данных. Сложно, но работает быстрее всего.
     
  3. Apeckou

    Apeckou Elder - Старейшина

    Joined:
    23 Jan 2007
    Messages:
    143
    Likes Received:
    11
    Reputations:
    0
    короче я сделал 50/50
    по идее все должно быстро работать и при этом удачно все искать ^^