我正在尝试为我的网站创建一个产品搜索,其中用户可以搜索多种语言的产品,并(希望)得到模糊搜索结果,如果没有精确匹配。
id, pro_id, en, de, es, fr, it
列的pro_search
表。pro_id
列引用各自表中产品的id。在搜索列中,每种产品的翻译后的元都以不同的语言表示。meta is languages.$term
分隔的关键字is en, de, es, fr, it
term.$lang
指的是用户选择的语言因此,首先我执行一个基本的'LIKE‘SQL查询,看看是否有匹配,如果没有结果,我将查询所有产品,并使用similar_text()
函数创建一个按相似度排序的数组
例如,我搜索‘衬衫’,如果这个产品的元数据只包括单词‘衬衫’,这是很好的,但如果元数据包括‘蓝色品牌T恤’,这是更具描述性的,并为用户提供了一个按品牌搜索的机会,但这意味着搜索很可能会变得模糊,而不是通过LIKE
SQL查询找到。
这在某种程度上是可行的,但我想知道如何改进这一点,有没有更好的搜索方式,或者人们通常是怎么做的?我是否应该将元划分为每个单独的关键字,并尝试查看有多少个单词匹配,而不是将术语与整个元匹配?
$ids = [];
$params = ['%'.$term.'%'];
$sql = "SELECT * FROM pro_search WHERE $lang LIKE ?";
$stmt = DB::run($sql,$params);
$count = $stmt->rowCount();
if($count > 0){
// product search
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
array_push($ids,$id);
}
show_products($ids);
}else{
// product fuzzy search
$sql = "SELECT * FROM pro_search";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$result = $row[$lang];
similar_text($term,$result,$similarity);
$similar_array[$similarity][] = $id;
}
$closest_match = array_keys($similar_array);
rsort($closest_match);
$match_count = count($closest_match);
for($i=0; $i<$match_count; $i++){
foreach($similar_array[$closest_match[$i]] as $id){
array_push($ids,$id);
}
}
show_products($ids);
}
我以前问过类似的问题,人们给我指出了将该术语与元进行比较的不同方法(如levenshtein),但我看到的所有东西都是比较两个简单的单词(如苹果和橙子),这对于有成千上万种产品的现实应用程序来说并不够好,用户可以搜索任何东西(如在$term='literally anything';
中)。
关键问题:
发布于 2019-04-12 07:02:10
您正在寻找Full-Text Searches WITH QUERY EXPANSION
通过使用LIKE
运算符和正则表达式,MySQL支持文本搜索。但是,当文本列很大并且表中的行数增加时,使用这些方法会有一些限制:
LIKE
语句中的模式或常规expressions.LIKE
运算符和正则表达式搜索,很难有灵活的搜索查询,例如,查找其描述包含汽车但不包含排名的产品:无法指定结果集中的哪一行与搜索术语更相关。由于这些限制,MySQL扩展了一个非常好的特性,即所谓的全文搜索。从技术上讲,MySQL从启用的全文搜索列的单词创建索引,并对该索引执行搜索。MySQL使用一种复杂的算法来确定与搜索查询匹配的行。
为此,将用于搜索的列必须是文本类型和全文类型的索引,索引可以使用ALTER TABLE或CREATE INDEX给出,如果您使用phpMyAdmin来管理数据库,您可以通过转到该表的结构来执行此操作,然后在该列的操作下单击更多并选择全文。
在此之后,您可以使用匹配语法执行搜索。MATCH()获取要搜索的列。使用要搜索的字符串和一个可选修饰符,该修饰符指示要执行的搜索类型。
具有查询扩展功能的全文搜索:
在某些情况下,用户希望基于他们所拥有的知识来搜索信息。用户使用他们的经验来定义关键字来搜索信息,通常这些关键字太短。
为了帮助用户根据过短的关键字查找信息,MySQL全文搜索引擎引入了查询扩展的概念。
查询扩展用于扩大基于自动相关反馈的全文搜索的搜索结果(或盲查询扩展)。从技术上讲,MySQL全文搜索引擎在使用查询扩展时会执行以下步骤:
根据相关的单词而不是用户提供的原始关键字再次执行搜索。MySQL
下面的示例展示了如何搜索其产品名称或meta至少包含一个单词的产品(衬衫、T恤)。
SELECT * FROM products WHERE MATCH(product_name,product_meta) AGAINST('shirt tshirt' WITH QUERY EXPANSION)
你可以在MYSQL文档(答案开头的链接)和here中阅读更多信息。
发布于 2019-04-11 04:03:05
如果你还在设计这个系统,你可以有一点不同的想法。在搜索方面,只需执行精确搜索,并按照前面的建议在db中执行,因为这要快得多-但“从每次交互中学习”。
所以基本的想法是,你可以从每个互动中学习,丰富你的搜索集。此外,当术语是用户,并且用户实际点击您的项目时,随着您对术语与产品关联的信心的提高,您将对该术语与产品的关联进行计数。
类似地,当你呈现一个选项时,用户应该能够很容易地说“不是这个”,然后引导他们通过预先选择的项目层次结构,最终当他们选择一个时,你将他们的搜索词保存到产品中。
因此,在几个月内,如果你获得了足够的用户,你就会有一个丰富的有机搜索术语数据集,用于你的产品类别,每个术语的置信度水平。
发布于 2019-04-05 17:17:49
您可以在sql中使用SOUNDEX。
SELECT * FROM users
WHERE SOUNDEX(job)
LIKE CONCAT('%',SUBSTRING(SOUNDEX('Manual worker'),2),'%');
像Manual worka
这样的东西将会起作用。您只需调整该值(当前为2
)即可满足您的需要。
我看到您已经尝试过Levenshtein算法,但您应该注意this adaptation (它也与UTF-8字符串兼容)
对我来说,soundex更有效,这取决于你的用户如何与你的应用程序交互。
但正如评论中所说,像ElasticSearch或Algolia这样的第三方可以更有效率。
我从来没有用过它,因为公司不允许我们使用第三方软件。这就是为什么我尝试了Levensthein和Soundex
https://stackoverflow.com/questions/55147321
复制相似问题