php / mysql:自定义网站搜索

时间:2011-04-27 23:00:33

标签: php mysql search

首先: - 我不能使用狮身人面像,因为我使用共享托管 - 我不喜欢谷歌解决方案即。自定义搜索有这些愚蠢的广告和网站搜索不是免费的

我想自己创建搜索机制。我有页面表,我想通过关键字和结果页面搜索页面内容我想显示与所需关键字匹配的部分文本(与谷歌一样)。

Thx in advanced

1 个答案:

答案 0 :(得分:1)

然后你有两个(和一半)选择:

  • 将MyISAM引擎用于您要搜索的数据
  • 编写自己的索引事物
  • 更改托管或更改DBMS(1/2解决方案)

以下是如何执行第二个选项的简短版本:

假设您要搜索文章的内容。 基本上你必须创建一个你可能想要搜索的所有单词的索引。

下面的代码来自本书SQL Antipatterns ,仅修改了一点点。

我假设您要索引文章:

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。我从来不需要测试这种方法,这就是为什么我不能保证它会起作用的原因。