我正在构建我的应用,使用单个搜索表搜索所有不同的对象类型,即:帖子,页面,产品等,基于this article.
我的表格布局如下:
CREATE TABLE IF NOT EXISTS myapp_search_index (
id int(11) unsigned NOT NULL,
language_id int(11) unsigned NOT NULL,
`type` varchar(24) COLLATE utf8_unicode_ci NOT NULL,
object_id int(11) unsigned NOT NULL,
`text` text COLLATE utf8_unicode_ci NOT NULL
PRIMARY KEY (id,language_id),
FULLTEXT KEY `text.fdx` (`text`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
我的搜索查询如下:
$items = $db->escape($query);
$query = $db->query("
SELECT *,
SUM(MATCH(text) AGAINST('+{$items}' IN BOOLEAN MODE)) as score
FROM {$db->prefix}search_index
WHERE MATCH(text) AGAINST('+{$items}' IN BOOLEAN MODE)
GROUP BY language_id, type, object_id
ORDER BY score DESC
LIMIT " . (int)$start . ", " . (int)$limit . "
");
除非我们遇到诸如停用词和最小字长等全文限制,否则这种方法很有用。
例如,我在About Us
页面的表格中有两个条目,一个包含页面标题,另一个包含页面内容。
运行查询about us
不会返回任何结果,因为about
是一个停用词,us
小于最少4个字母。
所以,我的想法是使用传统的LIKE
参数创建一个条件回退查询:
if (!$query->num_rows):
$query = $db->query("
SELECT *
FROM {$db->prefix}search_index
WHERE text LIKE '%{$items}%'
GROUP BY language_id, type, object_id
ORDER BY id DESC
LIMIT " . (int)$start . ", " . (int)$limit . "
");
endif;
再一次这很好用。我的About Us
页现在结果很好。
但我想要的是在一个查询中运行这一切并以某种方式保持得分。
这可能吗?
编辑:
好的,回应迈克尔的回答和评论,我已经改变了我的疑问:
SELECT *,
SUM(MATCH(text) AGAINST('{$search}' IN BOOLEAN MODE)) as score
FROM {$db->prefix}test_index
WHERE (
MATCH(text) AGAINST('{$search}' IN BOOLEAN MODE)
AND text LIKE '%{$search}%')
OR text LIKE '%{$search}%'
GROUP BY language_id, type, object_id
ORDER BY score DESC
我设置了一个包含100K行的测试表,其中50K包含我的lorem ipsum
搜索字词。
查询整个表并以0.6379微秒的速度返回结果,但尚未进行任何查询缓存。
有人能告诉我这是否是一个公平的妥协?
答案 0 :(得分:0)
使用多字词来玩自然语言模式:
SELECT id,prod_name, match( prod_name )
AGAINST ( '+harpoon +article' IN NATURAL LANGUAGE MODE) AS relevance
FROM testproduct
ORDER BY relevance DESC
我们经常只使用solr
集成,在其上投放json csv和文本文件。
答案 1 :(得分:0)
没有办法优雅地将全文搜索与LIKE
结合起来以获得更多结果。
这是因为两个谓词必须与OR
组合,这反过来意味着需要进行全表扫描(或者如果存在合适的BTREE
则进行全索引扫描)以进行测试LIKE
表达式。必须评估所有行,这将删除您从全文搜索中获得的任何优化。
在相反的情况下,将MATCH
和LIKE
结合使用AND
而不是OR
- 在全文匹配返回不够精确匹配的情况下 - 效果很好,因为优化程序使用全文索引查找所有可能匹配的行,然后根据LIKE
表达式筛选标识的行。 (当存在其他可能的查询计划时,优化器几乎总是首选全文索引。)不幸的是,这与您需要的相反。