0

我在 MySQL 5.5.22 上的多个表上运行全文查询。该应用程序使用 innodb 表,因此我创建了一些专门用于全文搜索的 MyISAM 表。

例如,我的一些表看起来像

account_search
===========
id
account_id
name
description
hobbies
interests

product_search
===========
id
product_id
name
type
description
reviews

由于这些表仅用于全文搜索,因此它们是非规范化的。数据可以来自多个表并聚合到搜索表中。除了 ID 列之外,其余列都分配给 1 个全文索引。

为了解决全文搜索的“50%”规则,我使用IN BOOLEAN MODE.

因此,对于上述情况,我会运行:

SELECT *, MATCH(name, type, description, reviews) AGAINST('john') as relevance
FROM product_search
WHERE MATCH(name, type, description, reviews) AGAINST('john*' IN BOOLEAN MODE) LIMIT 10

SELECT *, MATCH(name, description, hobbies, interests) AGAINST('john') as relevance
FROM account_search
WHERE MATCH(name, description, hobbies, interests) AGAINST('john*' IN BOOLEAN MODE) LIMIT 10

让我们假设我们也有名为“john”的产品:P

我面临的问题是:

  • 为了获得有意义的相关性,我需要使用不带IN BOOLEAN MODE. 这意味着搜索受 50% 规则和字长规则的约束。product_search因此,很多时候,如果我调用了表中的大多数产品john,它们的相关性将返回为 0。

  • 多个查询之间的相关性不具有可比性。(我认为来自一个查询的 14 的相关性不等于来自另一个不同查询的 14 的相关性)。

  • 搜索不仅限于这两个表,还有其他“对象类型”,例如:“订单”、“交易”等。

我希望能够返回给定一组关键字的所有对象类型的前 7 个最相关的结果(1 个搜索框返回所有对象的结果)。

鉴于上述情况,获得前 7 名的算法或更好的想法是什么?

我知道我可以使用 solr 和 elasticsearch 之类的东西,我已经尝试过它们并且正在将它们集成到应用程序中,但我希望能够为那些只能访问 MySQL 的人提供搜索。

4

1 回答 1

0

所以在考虑了一段时间后,我决定相关性排名必须在 MySQL 中使用 1 个查询来完成。

这是因为:

  • 无法比较单独查询之间的相关性。
  • 很难以有意义的方式将多个搜索的内容组合在一起。

我已切换到使用 1 个专用于搜索的索引表。条目的插入、删除和更新取决于对 innodb 表中真实基础数据的插入、删除和更新(这都是自动的)。

该表如下所示:

search
==============
id //id for the entry
type //the table the data came from
column //column the data came from
type_id //id of the row the in the original table
content //text

内容列上有一个全文索引。重要的是要意识到并非所有表中的所有列都会被索引,只有我认为在搜索中有用的东西才会被添加。

因此,这只是运行查询以匹配 on content、检索我们拥有的内容并进行进一步处理的简单案例。为了处理最终结果,需要更多的查询来向父表询问搜索结果的标题,也许还有其他一些元数据,但这是一个可行的解决方案。

我认为这种方法不会真正扩展(更新和插入也需要更新此表),但我认为这是为应用程序的较小部署提供体面的应用程序范围搜索的一种很好的方法。

对于可扩展性,请使用弹性搜索、solr 或 lucene 之类的东西。

于 2012-04-20T02:50:43.833 回答