PHP MySQL поисковые запросы - PullRequest
       1

PHP MySQL поисковые запросы

7 голосов
/ 29 августа 2011

Я пытаюсь создать поисковую систему для сайта на основе инвентаря. Проблема в том, что у меня есть информация внутри bbtags (как в [b]test[/b] sentence, test должен оцениваться в 3, тогда как sentence должен оцениваться в 1).

Вот пример индекса:
My test sentence, my my (имеет SKU TST-DFS)
База данных:

|Product|  word  |relevancy|
|   1   |   my   |    3    |
|   1   |  test  |    1    |
|   1   |sentence|    1    |
|   1   | TST-DFS|    10   |

Но как бы я сопоставил TST-DFS, если бы пользователь ввел TST DFS? Я хотел бы, чтобы у этого SKU была актуальность, скажем, 8 вместо полной 10 ..

Я слышал, что функция поиска FULL TEXT в MySQL поможет, но я не могу найти хороший способ сделать это. Я хотел бы избежать таких вещей, как UNIONS, и сделать запрос максимально оптимизированным.

Было бы здорово помочь с созданием хорошей системы для этого.

Спасибо, Max

Ответы [ 8 ]

5 голосов
/ 31 августа 2011

Но как бы я соответствовал TST-DFS, если бы пользователь ввел TST DFS?
Мне бы хотелось, чтобы у этого SKU была релевантность, скажем, 8 вместо целых 10 ..

Если я правильно понял вопрос, ответ на самом деле прост.
Что ж, если вы подделаете ваш запрос, прежде чем отправить его в mysql.

Хорошо, давайтескажем, у нас есть $query, и он содержит TST-DFS.

Мы собираемся сосредоточиться на диапазонах слов ?Я полагаю, что мы должны, , как и большинство поисковых систем , поэтому:

$ok=preg_match_all('#\w+#',$query,$m);

Теперь , если этот шаблон соответствует ... $m[0], содержит список слов в $query.
Это может быть точно настроено для вашего SKU, но сопоставление с полными словами в стиле AND - это почти то, что предполагает пользователь.(как это происходит в Google и Yahoo)

Затем нам нужно приготовить выражение $expr, которое будет введено в наш последний запрос.

if(!$ok) { // the search string is non-alphanumeric
  $expr="false";
} else {   // the search contains words that are no in $m[0]
  $expr='';
  foreach($m[0] as $word) {
    if($expr)
      $expr.=" AND ";  // put an AND inbetween "LIKE" subexpressions
    $s_word=addslashes($word); // I put a s_ to remind me the variable
                                 // is safe to include in a SQL statement, that's me 
    $expr.="word LIKE '%$s_word%'"; 
  }
}

Теперь $expr должно выглядеть следующим образом: "words LIKE '%TST%' AND words LIKE '%DFS%'"

С этим значением мы можем построить окончательный запрос:

$s_expr="($expr)";
$s_query=addslashes($query);

$s_fullquery=
"SELECT (Product,word,if((word LIKE '$s_query'),relevancy,relevancy-2) as relevancy) ".
"FROM some_index ".
"WHERE word LIKE '$s_query' OR $s_expr";

, который будет читать"TST-DFS":

SELECT (Product,word,if((word LIKE 'TST-DFS'),relevancy,relevancy-2) as relevancy)
FROM some_index
WHERE word LIKE 'TST-DFS' OR (word LIKE '%TST%' AND word LIKE '%DFS%')

Как видите, в первой строке SELECT, , если совпадение является частичным, mysql вернет релевантность-2

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

2 голосов
/ 29 августа 2011

Мне нравится все в нижнем регистре и вырезать специальные символы (например, в номере телефона или кредитной карте, я вынимаю все с обеих сторон, кроме числа)

1 голос
/ 02 сентября 2011

Я думаю, что решение довольно простое, если я не пропустил что-то.

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

Соедините два набора результатов вместе, как совпадение слева, и точное совпадение. Тогда, например:

final_relevancy = (IFNULL(like_relevancy, 0) + IFNULL(exact_relevancy, 0) * 3) / 4

Хотя я и сам не пробовал. Просто идея.

1 голос
/ 31 августа 2011

Создать таблицу ключевых слов. Что-то вроде:

integer keywordId (autoincrement) | varchar keyword | int pointValue

Назначьте в эту таблицу все возможные ключевые слова, skus и т. Д. Создайте еще одну таблицу, мост пост-ключевых слов (при условии, что postId - это идентификатор, который вы присвоили в исходной таблице) по строкам:

integer keywordId | integer postId

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

SELECT sum(pointValue) FROM keywordPostsBridge kpb 
JOIN keywords k ON k.keywordId = kpb.keywordId
WHERE kpb.postId = YOUR_INTENDED_POST
1 голос
/ 29 августа 2011

Вместо того, чтобы пытаться создать собственное решение FTS, вы можете попытаться приспособить движок MySQL FTS к вашим требованиям. То, что я видел, это создание новой таблицы для хранения ваших данных FTS. Создайте столбец для каждого отдельного фрагмента данных, который вы хотите иметь разную релевантность. Для вашего поля sku вы можете хранить необработанные sku с пробелами, подчеркиванием, дефисом и любым другим специальным символом без изменений. Тогда сохраните урезанную версию со всеми этими удаленными вещами. Вы также можете сохранить версию с удаленными начальными нулями, так как люди часто пропускают подобные вещи. Вы можете хранить все эти варианты в одном столбце. Сохраните название вашего продукта в другом столбце, а описание продукта в другом столбце. Создайте отдельный индекс для каждого столбца. Затем, когда вы выполняете поиск, вы можете искать каждый столбец по отдельности и умножать рейтинг результатов в зависимости от того, насколько важен этот столбец. Таким образом, вы можете умножить результаты sku на 10, заголовок на 5 и оставить результаты описания как есть. Возможно, вам придется немного поэкспериментировать, чтобы получить желаемые результаты, но в конечном итоге это может оказаться проще, чем создание собственного индекса.

0 голосов
/ 10 февраля 2013
it is a page coading where query result shows

**i can not use functions by use them work are more easier**

 <html>
 <head>
 </head>
 <body>
 <?php
//author S_A_KHAN
//date 10/02/2013
 $dbcoonect=mysql_connect("127.0.0.1","root");
 if (!$dbcoonect)
{
die ('unable to connect'.mysqli_error());
 }
 else
 {
 echo "connection successfully <br>";

 }
 $data_base=mysql_select_db("connect",$dbcoonect);


 if ($data_base==FALSE){

die ('unable to connect'.mysqli_error($dbcoonect));
  }
 else
  {
echo "connection successfully done<br>";
    ***$SQLString = "select * from user where id= " . $_GET["search"] . "";
$QueryResult=mysql_query($SQLString,$dbcoonect);***

echo "<table width='100%' border='1'>\n";
    echo "<tr><th bgcolor=gray>Id</th><th bgcolor=gray>Name</th></tr>\n";
    while (($Row = mysql_fetch_row($QueryResult)) !== FALSE) {
        echo "<tr><td bgcolor=tan>{$Row[0]}</td>";
        echo "<td bgcolor=tan>{$Row[1]}</td></tr>";
    }
}
?>

 </body>
 </html>
0 голосов
/ 02 сентября 2011
/*
q and q1 - you table
this query takes too much resources,
make from it update-query ( scheduled task or call it on_save if you develop new system )
*/
SELECT
       CASE
              WHEN word NOT REGEXP "^[a-zA-Z]+$"
                     /*many replace with junk characters
                     or create custom function
                     or if you have full db access install his https://launchpad.net/mysql-udf-regexp
                     */
              THEN REPLACE(REPLACE( word, '-', ' ' ), '#', ' ')
              ELSE word
       END word ,
       CASE
              WHEN word NOT REGEXP "^[a-zA-Z]+$"
              THEN 8
              ELSE relevancy
       END           relevancy
FROM   ( SELECT 'my' word,
               3     relevancy

       UNION

       SELECT 'test' word,
              1      relevancy

       UNION

       SELECT 'sentence' word,
              1          relevancy

       UNION

       SELECT 'TST-DFS' word,
              10 relevancy
       )
       q

UNION

SELECT *
FROM   ( SELECT 'my' word,
               3     relevancy

       UNION

       SELECT 'test' word,
              1      relevancy

       UNION

       SELECT 'sentence' word,
              1          relevancy

       UNION

       SELECT 'TST-DFS' word,
              10 relevancy
       )
       q1
0 голосов
/ 29 августа 2011

Я бы добавил столбец, в котором удалены все специальные символы, орфографические ошибки, а затем в верхнем регистре (или создал бы функцию, которая сравнивает текст, который был удален и в верхнем регистре). Таким образом, ваша актуальность будет последовательной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...