当前位置: 首页 > 面试题库 >

PHP / SQL-改进搜索功能/模糊搜索

戚建华
2023-03-14
问题内容

我正在尝试为我的网站创建一个产品搜索,用户可以在其中搜索多种语言的产品,如果没有完全匹配的内容,则(希望)获得模糊的搜索结果。

  • 我有一个pro_search带有列的表id, pro_id, en, de, es, fr, it
  • pro_id列指的是其各自表中产品的ID。
  • 这些en, de, es, fr, it列具有各种语言的每种产品的翻译后的meta。
  • 元只是由空格分隔的关键字
  • $term 是搜索词。
  • $lang 指用户选择的语言

因此,首先,我执行一个基本的“ LIKE”
SQL查询以查看是否存在匹配项,如果没有结果,则查询所有产品,并使用similar_text()函数创建一个按其相似性排序的数组

例如,我搜索“衬衫”,如果此产品的元数据仅包含单词“衬衫”,则很好,但如果元数据包含“蓝色品牌的T恤”,则说明性更强,并为用户提供了按品牌进行搜索的机会,但意味着搜索将很可能变得模糊,而不是通过LIKESQL查询找到。

这是一种工作,但是我想知道如何改进它,是否有更好的搜索方法,或者人们通常会如何做?我是否应该将meta分成每个单独的关键字,并尝试查看有多少个单词匹配,而不是将术语与整个meta匹配?

    $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);
    }

之前我曾问过类似的问题,人们指出了将术语与meta进行比较的不同方法(例如levenshtein),但是我所看到的一切都是在比较两个简单的单词(例如苹果和橘子),而这仅仅是“对于具有数千种产品的现实生活应用而言,它已经足够好了,用户可以搜索几乎所有内容(如中的$term='literally anything';

关键问题:

  • 我的元数据应该只包含产品名称还是多个相关的关键字(关键字过多意味着单个单词与整个单词不太相似)?
  • 如果我在中继资料中有多个关键字,应该将每个关键字与搜寻字词进行比较吗?
  • 也可能为单个产品使用否定关键字。

问题答案:

您正在寻找具有QUERY
EXPANSION的全文本搜索

MySQL通过使用LIKE运算符和正则表达式来支持文本搜索。但是,当文本列很大并且表中的行数增加时,使用这些方法会有一些局限性:

  • 性能:MySQL必须扫描整个表以根据LIKE语句中的模式或正则表达式中的模式找到确切的文本。
  • 灵活的搜索:通过LIKE运算符和正则表达式搜索,很难进行灵活的搜索查询,例如,查找描述中包含汽车而不是经典产品的产品。
  • 相关性排名:无法指定结果集中的哪一行与搜索字词更相关。

由于这些限制,MySQL扩展了一个非常好的功能,即所谓的全文搜索。从技术上讲,MySQL从已启用的全文搜索列的单词创建索引,然后对该索引执行搜索。MySQL使用复杂的算法来确定与搜索查询匹配的行。

为此,将用于搜索的列必须为TEXT类型,并且索引必须为FULLTEXT类型,可以使用ALTER
TABLE
或CREATE
INDEX给出索引,如果您使用phpMyAdmin管理数据库,则可以通过到该表的结构,然后在该列的“操作”下单击“更多”,然后选择“全文本”。

之后,您可以使用MATCH
AGAINST语法执行搜索。MATCH()获取要搜索的列。AGAINST需要一个字符串来搜索,以及一个可选的修饰符,该修饰符指示要执行的搜索类型。

具有QUERY EXPANSION的全文本搜索:

在某些情况下,用户希望基于其所拥有的知识来搜索信息。用户使用他们的经验来定义关键字来搜索信息,并且通常这些关键字太短。

为了帮助用户根据太短的关键字查找信息,MySQL全文搜索引擎引入了一种称为查询扩展的概念。

查询扩展用于基于自动相关性反馈(或盲查询扩展)来扩展全文搜索的搜索结果。从技术上讲,使用查询扩展时,MySQL全文搜索引擎执行以下步骤:

  • 首先,MySQL全文搜索引擎查找与搜索查询匹配的所有行。
  • 其次,它检查搜索结果中的所有行并找到相关的单词。
  • 第三,它根据相关单词而不是用户提供的原始关键字再次执行搜索。

以下示例显示了如何搜索产品名称或元数据至少包含一个单词的产品(衬衫T恤)。

SELECT * FROM products WHERE MATCH(product_name,product_meta) AGAINST('shirt tshirt' WITH QUERY EXPANSION)


 类似资料:
  • 用NSPredicate类写的一个简单的模糊搜素方法,比for循环快并且性能消耗很低。 [Code4App.com]

  • 我正在尝试实现一个二叉查找树,但是“搜索”函数对于除了根之外的每个条目都返回了错误的值。 该函数应返回其值与键参数匹配的节点的地址,如果节点不存在,则返回 NULL。 当我运行代码时,我得到以下内容: 我知道每个节点的“左”和“右”指针链接正确,因为“delAll”函数成功删除了所有节点。 将“cout”语句添加到“search”函数表明该函数似乎返回了正确的地址。为什么从主主调用时会打印错误的地

  • 问题内容: 我正在使用SQL Server 2008 R2 SP1。 我有一张约有36034个客户记录的表。我正在尝试在“客户名称”字段上实施Fuzy搜索。 这是模糊搜索的功能 这是调用该函数的查询 这大约需要2分22秒,可以为我提供所有对象的模糊匹配百分比 我如何解决此问题以在不到一秒钟的时间内运行。关于我的功能的任何建议,以使其更强大。 预期输出为45.34、40.00、100.00、23.0

  • 问题内容: 我想知道是否有任何Python库可以进行模糊文本搜索。例如: 我有三个关键字 “ letter” , “ stamp” 和 “ mail” 。 我想要一个功能来检查这三个词是否在同一段落(或一定距离,一页)内。 另外,这些词必须保持相同的顺序。在这三个词之间出现其他词也很好。 我已经尝试过解决不了我的问题。另一个库看起来很强大,但是我找不到合适的功能… 问题答案: {1} 您可以在中执

  • 12.7.1. 布尔全文搜索 12.7.2. 全文搜索带查询扩展 12.7.3. 全文停止字 12.7.4. 全文限定条件 12.7.5. 微调MySQL全文搜索 MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION]) MySQL支持全文索引和搜索功能。MySQL中的全文索引类型FULLTEXT的索

  • 本文向大家介绍C ++ STL中的二进制搜索功能,包括了C ++ STL中的二进制搜索功能的使用技巧和注意事项,需要的朋友参考一下 二进制搜索是一种搜索算法,用于查找目标值在排序数组中的位置。二进制搜索将目标值与已排序数组的中间元素进行比较。二进制搜索的时间复杂度为O(1)。这是一个我们实现各种C ++程序。C ++ STL中的二进制搜索功能 算法 范例程式码 输出结果