我有一个名为keywords的表。它很简单,有两列--id和关键字。此表总是在增长,我们总是会向其中添加其他内容。
现在,我们有一个用户提交的2-3句话段落。我们想要检查关键字表中所有关键字在本段中的单词。
最有效的方法是什么?我的初始逻辑在
之下// explode $paragraph into $words[]
// cycle through $words -- in each loops, SQL statement where $word = keyword
// output any matched keywords
这会是最有效的吗?请记住,关键字表可以是几千行。我应该使用Sphinx搜索解决方案吗?
答案 0 :(得分:4)
查询:
SELECT id, keyword FROM tbl_name WHERE keyword IN ('word1', 'word2', 'word3', 'wordN');
必须插入尚未返回的单词。
答案 1 :(得分:1)
有一系列被排除的单词。 (或者从数据库中提取它,或者其他什么。)
$excludeThis = array(
'a',
'the',
'for',
);
剥去所有的点,斜线等。
$text = preg_replace('/[^A-Za-z0-9]/', ' ', $text);
$text = str_replace(' ', ' ', $text);
分解文字
$words = explode(' ', $text);
根据您的关键字构建您想要匹配的所有字词的数组。
$array = array();
if ( ! empty($words)) {
foreach ($words as $word) {
if (in_array(strtolower(trim($word)), $excludeThis))
continue;
$array[] = strtolower(trim($word));
}
}
从数据库中提取您的关键字(您可能实际上想要缓存此...)并且只需使用array_intersect()来匹配您的两个数组。
不知道这是否是最快的方式,但也许有帮助。
答案 2 :(得分:0)
我认为这是正确的方法。但我更喜欢第二张桌子(小得多),你的段落中常常有排除的词语(例如'和','或',''等等......)。从$ words中消除所有这些单词,你可以节省几毫秒。
答案 3 :(得分:0)
这是使用存储过程的绝佳机会。 Crozin的反应会起作用,但我更喜欢在数据库中保留这种逻辑。
理由:
如果您决定在以后添加/删除/重命名列 - 或者如果您有幸在项目中拥有DBA - 那么维护起来会更容易。
如果您是从用户输入生成单词列表,它将有助于防止SQL注入。我将站点的db用户帐户的权限限制为执行存储过程的能力。
在任何一种情况下,逻辑都保持不变。将段落Split换成单词,并使用“in”将关键字列与该列表进行比较。
或者,如果您正在处理大量文本,将结果单词列表拆分并转换为行(可能在临时表中)并从连接中选择可能更有效:
select *
from keywords
join #paragraph_words
on keywords.keyword=#paragraph_words.keyword;
(你必须检查语法,因为我现在没时间验证它。)
集合运算符(如IN
)可能不会像连接一样好,但正如我所说,如果你只处理一个短单词列表,那就太过分了。
答案 4 :(得分:0)
多次查询数据库不是最有效的方法。
我猜您可以使用MySQL Full-text search功能来解决您的问题。它不会在高负载下扩展,但对于大多数站点,它将快速完成工作。
如果你想要最优化的解决方案,你应该学习像elasticsearch,solr,sphinx,lucene等产品。因为它们是为了解决这个问题而写的。