PHP / MySQL: простая поисковая система - PullRequest
2 голосов
/ 19 марта 2012

Я собираю простой поисковик для небольшого сайта. Пользователи смогут искать своих друзей по email address или name. Я надеялся использовать поиск FULLTEXT, но я использую таблицы InnoDB, поэтому я возвращаюсь к LIKE %keyword%.

Моя проблема в том, что имена и фамилии пользователей хранятся в двух отдельных столбцах. Как мне найти «правило Дэвида» в такой ситуации?

Вот что у меня есть на данный момент:

    if(filter_var($query,FILTER_VALIDATE_EMAIL)) {
        $STH = $this->_db->prepare("SELECT UserID
            FROM UserCredTable
            WHERE EmailAddress = :query;");
    } else {
        $STH = $this->_db->prepare("SELECT UserID
            FROM UserInfoTable
            WHERE FirstName LIKE :query
            OR LastName LIKE :query;");
    }

Это вроде работает, но я предполагаю, что релевантность практически отсутствует: (

Как сортировать по наиболее релевантным результатам?


Обновление:

Это похоже на приличное решение?

    if(filter_var($query,FILTER_VALIDATE_EMAIL)) {
        $params["query"] = $query;
        $STH = $this->_db->prepare("SELECT UserID
            FROM UserCredentials
            WHERE EmailAddress = :query;");
    } else {
        $params["query"] = "%".$query."%";
        $STH = $this->_db->prepare("SELECT UserID
            FROM UserDetails
            WHERE CONCAT(FirstName,' ',LastName) 
            LIKE :query;");
    }

Ответы [ 5 ]

3 голосов
/ 19 марта 2012

Взгляните на Sphinx , он индексирует данные непосредственно из MySQL и имеет PHP API для поиска.

Кроме того, вы можете разделить пробелы в тексте поиска и попробовать несколько ИЛИ, но, как вы сказали, релевантность в InnoDB отсутствует.

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

0 голосов
/ 19 марта 2012

Если полнотекстовый поиск не подходит, вам, вероятно, придется посмотреть на разделение поискового запроса и запросить что-то вроде этого:

SELECT UserID
FROM UserInfoTable
WHERE (FirstName LIKE '%David%'
OR LastName LIKE '%David%') OR
(FirstName LIKE '%:Rule%'
OR LastName LIKE '%:Rule%')

Не идеально, и я не уверен, что это лучшее решение, но оно, вероятно, вернет лучший результат для вас. Особенно, если у людей появляются тройные имена (например, «Джон Тейлор Смит»), которые, похоже, становятся все более распространенными

0 голосов
/ 19 марта 2012

Вы можете использовать функцию CONCAT () в MySQL

} else {
     $STH = $this->_db->prepare("SELECT UserID
         FROM UserInfoTable
         WHERE CONCAT(FirstName,LastName) LIKE '%:query%';");
 } 
0 голосов
/ 19 марта 2012

Поиск, очевидно, является большой темой, и существует множество различных способов обработки вещей.

При этом для наиболее простого возможного решения вы должны иметь возможность поиска по объединению этих двух полей:

SELECT UserID
        FROM UserInfoTable
        WHERE CONCAT(FirstName, ' ', LastName) LIKE '%Dave Smith%';

Функция MySQL CONCAT() принимает столько строк, сколько вы объединяете в качестве аргументов.В приведенном выше случае мы просто добавили пробел между FirstName и LastName .

0 голосов
/ 19 марта 2012

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

Это добавляет ранжирование к вашему поиску, это довольно круто.

Следующий пример взят из руководства MySQL, http://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html

mysql> CREATE TABLE articles (
    ->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    ->   title VARCHAR(200),
    ->   body TEXT,
    ->   FULLTEXT (title,body)
    -> ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles (title,body) VALUES
    -> ('MySQL Tutorial','DBMS stands for DataBase ...'),
    -> ('How To Use MySQL Well','After you went through a ...'),
    -> ('Optimizing MySQL','In this tutorial we will show ...'),
    -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    -> ('MySQL vs. YourSQL','In the following database comparison ...'),
    -> ('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM articles
    -> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...