php / mysql: пользовательский поиск по сайту - PullRequest
0 голосов
/ 28 апреля 2011

Прежде всего: - Я не могу использовать сфинкс, потому что я использую общий хостинг - Я не люблю решения Google, т.е. Пользовательский поиск имеет эти глупые объявления, и поиск по сайту не бесплатный

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

Спасибо за продвинутый

1 Ответ

1 голос
/ 28 апреля 2011

Тогда у вас есть два (с половиной) выбора:

  • используйте движок MyISAM для данных, которые вы хотите найти
  • написать свою собственную вещь для индексации
  • сменить хостинг или сменить СУБД (решение 1/2)

Вот краткая версия того, как вы можете 2-й вариант :

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

Код ниже взят из книги Антипаттерны SQL и изменен лишь крошечный бит.

Я предполагаю, что вы хотите проиндексировать статьи:

CREATE TABLE Articles(
   article_id INT AUTO_INCREMENT,
   title VARCHAR(120),
   content TEXT,
   PRIMARY KEY ( article_id )
);

Вам нужна таблица для ключевых слов (каждое ключевое слово может быть в нескольких статьях):

CREATE TABLE Keywords(
   keyword_id INT AUTO_INCREMENT,
   keyword VARCHAR(40) UNIQUE NOT NULL,
   PRIMARY KEY ( keyword_id )
);

Теперь таблица для реализации отношения «многие ко многим»:

CREATE TABLE ArticlesKeywords(
   keyword_id INT,
   article_id INT,
   PRIMARY KEY ( keyword_id , article_id ),
   FOREIGN KEY ( keyword_id ) REFERENCES Keywords( keyword_id ),
   FOREIGN KEY ( article_id ) REFERENCES Articles( article_id )
);

И затем вы создаете хранимую процедуру, которая заполняет ваш механизм индексации:

CREATE PROCEDURE ArticlesSearch(keyword VARCHAR(40))
BEGIN
   SET @keyword = keyword;
   PREPARE s1 FROM 'SELECT MAX(keyword_id) INTO @k FROM Keywords
      WHERE keyword = ?';
   EXECUTE s1 USING @keyword;
   DEALLOCATE PREPARE s1;
   IF (@k IS NULL) THEN

      PREPARE s2 FROM 'INSERT INTO Keywords (keyword) VALUES (?)';
      EXECUTE s2 USING @keyword;
      DEALLOCATE PREPARE s2;

      SELECT LAST_INSERT_ID() INTO @k;

      PREPARE s3 FROM 'INSERT INTO ArticlesKeywords (article_id, keyword_id)
         SELECT article_id, ? FROM Articles
         WHERE title REGEXP CONCAT(''[[:<:]]'', ?, ''[[:>:]]'')
            OR content REGEXP CONCAT(''[[:<:]]'', ?, ''[[:>]]'')';
      EXECUTE s3 USING @k, @keyword, @keyword;
      DEALLOCATE PREPARE s3;

   END IF;

   PREPARE s4 FROM 'SELECT b.*FROM Articles b
      JOIN ArticlesKeywords k USING (article_id)
      WHERE k.keyword_id = ?';
   EXECUTE s4 USING @k;
   DEALLOCATE PREPARE s4;
END

Теперь вы можете использовать эту процедуру для поиска по индексу по ключевому слову.

CALL ArticlesSearch('OMG');

Последняя часть решения заключается в том, что каждая новая статья автоматически индексируется:

CREATE TRIGGER Articles_Insert AFTER INSERT ON Articles
FOR EACH ROW
BEGIN
   INSERT INTO ArticlesKeywords (article_id, keyword_id)
      SELECT NEW.article_id, k.keyword_id FROM Keywords k
      WHERE NEW.content REGEXP CONCAT('[[:<:]]', k.keyword, '[[:>:]]')
         OR NEW.title REGEXP CONCAT('[[:<:]]', k.keyword, '[[:>:]]');
END

.

P.S. Мне никогда не нужно было проверять этот подход, поэтому я не могу гарантировать, что он будет работать.

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