download.bg
 Вход Списание  Новини  Програми  Статии  Форум  Чат   Абонамент  Топ95   Архив 

Търсене в две полета - логически израз?

Автор
Съобщение
insecteater
Вто, 05.12.06, 10:27
Има ли програмисти из тоя сайт? Функциите са на php, но това няма значение за логиката.
------------------Въведение--------------------------
Всички знаете как се търси с търсачка. търсеното трябва да съдържа всички думи зададени в полето за търсене, но НЕ трябва да съдържа думи, пред които има знака минус.
Та аз имам такава функция. search($what, $container), която връща true ако намери нещо и false ако не намери. Дотук всичко добре. Ето даже един пример:
Христо -Ботев

Връща true за всичко, което съдържа думата "Христо" и НЕ съдържа думата "Ботев"

-------------------Проблем----------------------------
Ситуацията обаче се обърква ако са замесени две или повече полета.
Например израза
search('Христо', $column1) || search('Христо', $column2)

ще върне true ако поне в едното поле се среща думата "Христо" както и се очаква
ОБАЧЕ
израза
search('Христо - Ботев', $column1) || search('Христо -Ботев', $column2)

ще върне true, даже ако в кое да е поле се среща думата "Ботев" (въпреки знака минус)
Идеята е ако поне в едното поле (а не и в двете, както е сега) се съдържа думата Ботев, да се върне false.
Един логически израз да става за всички случаи.

MySQL в случая не се използва изобщо.

Засега съм намерил решение като просто обединя двете полете (конкатенация).
Има ли логически израз който да замести конкатенацията И изобщо не е ли по рационално полетата да се съединяват и така да се претърсват, вместо да се търси логически израз.

редактиран от insecteater на 05.12.06 10:29
milen
Вто, 05.12.06, 11:09

RE: Търсене в две полета - логически израз?

Аз съм един от създателите на Download.BG, който е направен на PHP и MySQL. Разгледай търсачката, например в раздел програми. Имай предвид, че знака "-" при нас е заменен от "^". Това е така, защото повечето потребители не използват правилно знака "-" (дори и в Google, независимо от многото образователни статии по отношение синтаксиса на търсене). Много пишат Flash-get или "най-добрата програма за ". Кавичките за фраза също работят, но и без тях резултатите са подредени.

Може би мога да предложа решение на проблема, ако ми покажеш предметната област в която търсиш. Например при нас, правим предварителна конкатенация на полетата на всеки обект, за да можем да използваме едни и същи функции за пълнотекстово търсене. Паметта в базата данни не е толкова голям проблем, колкото правилността на търсенето и скоростта.

insecteater
Вто, 05.12.06, 12:31
Благодаря за отзива.
И аз мисля че съединяването е най добре, когато е въвлечен - (респ. ^). Така го оставих и без това.

Относно това::

Цитат
” Много пишат Flash-get или "най-добрата програма за ". „

Аз процедирам по следният начин:

1. Извличам фразите заградени с кавички в масив чрез регулярен израз (заедно със знака минус ако има пред тях), и ги премахвам от низа за търсене

2. След това низа за търсене го пренасям в масив, като използвам за разделител знака за интервал

3. Съединявам двата масива (голите думи и фразите)
отделям в отделен масив думите (фразите) ПРЕД които има знак минус, а в старият остават тези БЕЗ минус В НАЧАЛОТО

4. В зависимост от случая, съставям заявка за MySQL от елементите на масивите, или обхождам и прилагам stristr за всеки елемент (Ако няма MySQL).

по този начин flash-get ще търси за низа"'flash-get" и изобщо тиренцето което е вътре във фраза или словосъчетание, няма да бъде вземано в предвид.
Остава отрит въпроса как ще се интерпретира търсене от сорта на
flash-"get е най добрата"
Без интервал преди тирето. И как би трябвало да се интерпретира

P.S. Като стана готов, ще оставя адрес да покажа какво се е получило. Макар че имам нещо подобно на http://www.bghouses.com. Абсолютно целият сайт е моя изработка (+MySQL), но не помня вече как точно правих търсенето (Правен е отдавна и вече не съм отговорен за него, сорса е архивиран някъде из шкафа). Там обаче няма свободен низ за търсене и общо взето заявките се правят от долепване на критериите.

milen
Пон, 11.12.06, 10:27

Търсене в две полета - интерпретиране на заявката на потребителя

В Download.BG за статистиката пазим последните 2 милиона заявки за търсене. Разглеждал съм извадки от тях и мога да твърдя че потребителите въобще не се интересуват от синтаксиса за точно търсене. Това разбира се е така, защото потребителите на Download.BG в общия случай не са ИТ професионалисти. Съвсем малка част пробват неща като:
 - минус за изваждане от списъка с резултатите
 - AND OR за логически изрази
 - кавички за търсене на цели фрази
Програмистите живеят в обкръжение на програмисти и разбирането им за потребителите е изкривено. Потребителите искат да напишат една две думи и да получат желания резултат.

Затова в Download.BG ние направихме нещо друго: вдигаме рейтинга на резултати, където търсените думи се намират в същата последователност както са зададени от потребителя. Последователностите от думи се прекъсват от кавичките. Освен това проверяваме за слято изписване на думите: Например:

flash get ще търси най вече резултати където има flashget, "flash get, flash и get в тази последователност. Сега като гледам, на 10 заявки 7 успяват да намерят това, което търсят. разбира се има проблем със следните 2 групи потребители:
 - крайно неграмотните, които пишат например на български с латиница, например "programa za gledane na filmi" те са около 25% от потребителите;
 - "хакерите", които използват несъществуващ синтаксис като and, or и т.н.
Хайде, като направиш търсенето, ще го пробваме ;)

anonymous
Пон, 11.12.06, 15:35
Ако правилно съм разбрал въпроса:
<html>
<head><title>Search</title></head>
<body>
 
<?php
// Full-Text Search Example
// Conect to the database.
$cnx = mysql_connect('localhost', 'phpfreaks', 'phpfreaks') or die ("Could not connect");
mysql_select_db('phpfreaks_search',  $cnx) or die (mysql_error());
 
// Create the search function:
 
function searchForm()
{
  // Re-usable form
  
  // variable setup for the form.
  $searchwords = (isset($_GET['words']) ? htmlspecialchars(stripslashes($_REQUEST['words'])) : '');
  $normal = (($_GET['mode'] == 'normal') ? ' selected="selected"' : '' );
  $boolean = (($_GET['mode'] == 'boolean') ? ' selected="selected"' : '' );
  
  echo '<form method="get" action="'.$_SERVER['PHP_SELF'].'">';
  echo '<input type="hidden" name="cmd" value="search" />';
  echo 'Search for: <input type="text" name="words" value="'.$searchwords.'" />&nbsp;';
  echo 'Mode: ';
  echo '<select name="mode">';
  echo '<option value="normal"'.$normal.'>Normal</option>';
  echo '<option value="boolean"'.$boolean.'>Boolean</option>';
  echo '</select>&nbsp;';
  echo '<input type="submit" value="Search" />';
  echo '</form>';
}
 
 
// Create the navigation switch
$cmd = (isset($_GET['cmd']) ? $_GET['cmd'] : '');
 
switch($cmd)
{
  default:
    echo '<h1>Search Database!</h1>';
    searchForm();
  
  break;
  
  
  case "search":
    searchForm();
    echo '<h3>Search Results:</h3><br />';
    
    $searchstring = mysql_escape_string($_GET['words']);
    switch($_GET['mode'])
    {
      case "normal":
        $sql = "SELECT mytable_id, mytable_title, mytable_caption, mytable_dts, 
               MATCH(mytable_title, mytable_caption, mytable_full_body) 
               AGAINST ('$searchstring') AS score FROM mytable 
               WHERE MATCH(mytable_title, mytable_caption, mytable_full_body) 
               AGAINST ('$searchstring') ORDER BY score DESC";
      break;
      
      case "boolean":
        $sql = "SELECT mytable_id, mytable_title, mytable_caption, mytable_dts, 
               MATCH(mytable_title, mytable_caption, mytable_full_body) 
               AGAINST ('$searchstring' IN BOOLEAN MODE) AS score FROM mytable 
               WHERE MATCH(mytable_title, mytable_caption, mytable_full_body) 
               AGAINST ('$searchstring' IN BOOLEAN MODE) ORDER BY score DESC";
      break;
    } 
    
    // echo $sql;
    
    $result = mysql_query($sql) or die (mysql_error());
    
    while($row = mysql_fetch_object($result))
    {
      echo '<strong>Title: '.stripslashes(htmlspecialchars($row->mytable_title)).'</strong><br />';
      echo 'Score:'. number_format($row->score, 1).' Date: '.date('m/d/y', $row->mytable_dts).'<br />';
      echo '<p>'.stripslashes(htmlspecialchars($row->mytable_caption)).'</p>';
      echo '<hr size="1" />';
    }
  break;
}
?>
 
</body>
</html>

insecteater
Вто, 12.12.06, 11:59
yogi--, мерси и на теб. Чувствам се малко гузно. Имам един не толкова голям текстов файл с местоположения и координати на места от карти на една ИГРА. Т.е. на мен това не ми трябваше за нищо сериозно. MySQL изобщо не е замесен при мен. Но пък се получи хубаво преподаване на опит, за което благодаря. Иначе адреса е http://InsectEater.no-ip.info/mm7/locations.php (Сочи към моят компютър, а съм на БТК, така че има шанс да не се вижда от време на време, докато се update-не DNS-а). А там използвам както съм описал по-горе разделяне на думите и след това претърсване със stristr. Просто като гъбена чорба. Тежката артилерия на MySQL и е рано още . Иначе MATCH() ... AGAINST() наистина е доста гъвкаво, но на мен все още не ми се е налагало да ги използвам както трябва. Проектите ми все включват филтриране , отколкото търсене.

Колкото до това:
- крайно неграмотните, които пишат например на български с латиница, например "programa za gledane na filmi" те са около 25% от потребителите;
Ами ... не знам какво да кажа :( Ако наистина са 25% Сериозно почвам да се опасявам за бъдещето ни като "културна" нация.

P.S. Какъв е начина за търсене из форума и статиите на download.bg с включени ВСИЧКИ думи от заявката?

anonymous
Вто, 12.12.06, 13:08
Гоогле от тарсачката си направиха милярди.
микрософт /колегите ви/ са мъчат да го конкурират
а ти искаш да го направиш -сас фрее ...........
то се казва МАТЕМАТИКАТА на тарсачката,АЛГОРИТАМА и парво си изясни
даже при гоогле се случва като тарсиш нещо-да ти предложат .............19 милиона страници.
Ама на клиента му трябва само една-тази дето я иска тои.
проблема е чиста математика......
anonymous
Вто, 12.12.06, 18:09
Не знам дали ще мога да обесня идеята като хората. Работата е там, че не разполагам с много време в момента.
Та: Идеята е следната. Да кажем, че записваш търсения стринг в $what_search. Разделяме думите в него с $search_tmp = explode(" ", $what_search); За разделител използваме интервал-а и ги набиваме в масива $search_tmp. След което си правим един цикъл, разбира се, ако има нещо в този масив, и проверяваме всяка дума за някакъв знак. Минус, плус, кото там. И слагаме в нов масив $searching_for само тези думи, които трябва да пресъстват.
if ($search_tmp) { // Ако не е празен
   for ($i=0; $i <= sizeof($search_tmp); $i++) { // за всеки елемент от масива
      if (substr($search_tmp[$i], 0, 1) == '-') // в случая гледаме дали има -
         continue; // ако има редовете до края на цикъла не се изпълняват, а той си продължава
         $searching_for .= $search_tmp; // ако няма - вкарваме думата
   } // end of FOR
} // end of IF 
 

Така имаш масив $searching_for, който съдържа думите за търсене.
Може, разбира се, да се направи и по още различни начини. Просто, тея дни времето ми е малко недостатъчно ;(
Успех.

insecteater
Вто, 12.12.06, 18:28
 
function find($search, $container) {
    $search = stripslashes($search);
    $search = str_replace("&quot;", '"', $search);
 
    $quotes = array();
    //Extract phrases in quotes
    preg_match_all('/(-?)"(.*?)"/', $search, $phrases, PREG_SET_ORDER);
    //Delete extracted quotes
    $search = preg_replace('/-?"(.*?)"/', "", $search);
    //Phrases processing
    for ($i=0; $i < count($phrases); $i++) {
        $ph = $phrases[$i][2];
        
        //Find  the "-" sign
        if (chr(ord($phrases[$i][1])) == "-") {
            $ph = preg_replace("/^-/", "", $ph);
            $ph = '-'.$ph;
        }
        $quotes[] = $ph;
    }
    
    $search = explode (' ', $search);
    $search = array_merge($search, $quotes);
    $search = array_filter($search);
    foreach ($search as $word) {
        if ($word[0] == '-') {
            $word = substr($word, 1);
            if (stristr($container, $word)) return false;
        }
        elseif (!stristr($container, $word)) return false;
    }
    return true;
}

Ей тая функцийка съм си я сглобил отпреди месец - месец и половина някъде и си я ползвам за търсене на текст. Ако има предложения специално за кода по-горе, ще се радвам да ги видя.

Редакция: Редактирах заради специалните знаици - по специално &quot ;

редактиран от insecteater на 12.12.06 18:30

Коментар

за нас | за разработчици | за реклама | станете автори | in english  © 1998-2024   Experta Ltd.