如何实现搜索功能?

Posted

技术标签:

【中文标题】如何实现搜索功能?【英文标题】:How to implement search feature? 【发布时间】:2021-01-08 12:20:41 【问题描述】:

我的表中有一个字段关键字,其中存储了所有逗号分隔的关键字。 现在,我有一个输入词,我想使用表中的关键字字段从表中搜索与该输入匹配的所有项目。有没有更好的方法或者唯一的方法是对整个表进行线性搜索。

【问题讨论】:

您需要做的就是使用表中的关键字字段从表中搜索与该输入匹配的所有项目。 我的表中存储所有逗号分隔关键字的字段关键字将其规范化为(keyword_group_id, ordinal_position, one_keyword) @GrumpyCrouton 是的,我明白了,但我想问有没有其他方法 @Akina 你能详细说明一下吗?尽可能使用示例 @dhruvtailor 我们怎么知道?您需要提供更多详细信息。分解相关表的结构,给我们示例数据,示例搜索,示例预期收益 【参考方案1】:

一个例子。

现在你有一个看起来像这样的存储:

group_id | keywords
-----------------------------------------
   ...   |  ...
   123   |  word1,word2,word3
   124   |  word5,word2
   125   |  word3,word4,word1,word7,word8
   ...   |  ...

你把它转换成

group_id | ordinal | keyword
----------------------------
   ...       ...     ...
   123        1      word1
   123        2      word2
   123        3      word3
   124        1      word5
   124        2      word2
   125        1      word3
   125        2      word4
   125        3      word1
   125        4      word7
   125        5      word8
   ...       ...     ...

当您需要包含 'word2' 的组的组标识符时,您执行

SELECT group_id 
FROM keywords
WHERE keyword = 'word2'

将返回

group_id
--------
  123
  124

当您需要执行整个关键字组时

SELECT group_id, GROUP_CONCAT(group_id ORDER BY ordinal) keywords
FROM keywords
JOIN ( SELECT group_id 
       FROM keywords 
       WHERE keyword = 'word2' ) AS groups USING (group_id)

将返回

group_id | keywords
-------------------------------
   123   |  word1,word2,word3
   124   |  word5,word2

为了提高性能,您需要在表结构中创建适当的索引(通过(keyword, group_id)(group_id))。

【讨论】:

我很想将您的链接结构移动到多对多的位置,您可以在其中存储原始表 ID、序号位置和单词 ID(两个 ID 上的 PK)。然后你的词表可以有一个关于这个词的唯一索引,加快搜索速度。 @Skrrp 如果关键字在它所提及的所有组中同步(在一个组中更改必须在所有其他组中更改它),则为 true,否则上述结构更安全。 啊,我知道你是从哪里来的。我个人会将这些词视为不可变的,而不是“属于”左表中的任何记录。因此,如果有人“删除”了一个词,它就会删除 m2m。如果一个词被“编辑”,则 m2m 被删除并重新创建为新词(无论它是被插入的,还是已经存在的)。【参考方案2】:

我将推荐使用专用搜索索引。 Akina 的回答非常适合完全在 mysql 中执行此操作。如果您想在like '%ave%' 上匹配Dave,则需要阅读FULLTEXT 索引; MySQL manual.

不过,使用这种结构,您只构建了一半的搜索索引。您最好将真正的搜索索引引入您的堆栈。如今,使用 Laravel 和 Symfony 的库,或者仅使用 php 驱动程序(需要一些程序集),Elastic 真的很容易实现。一旦你有了搜索索引,它就会提供额外的好处,例如自动复数搜索,甚至会返回按匹配分数排序的结果。

您需要做的就是创建一个包含一个字段的搜索索引,然后为 MySQL 数据库中的每条记录用空格分隔所有单词。您的 Elastic 记录将如下所示:


    "_id": "[Elastic's record ID]",
    "mysql_id": "[Your ID in MySQL]",
    "search_field": "word1 word2 word3"

搜索此索引将为您返回用于搜索的 MySQL ID,然后您可以在您的 PHP 应用程序中进行水合。

【讨论】:

以上是关于如何实现搜索功能?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现jqGrid的多个搜索

在执行搜索功能期间如何实现 UIActivityIndi​​catorView?

如何实现基于多个参数的搜索功能?

如何实现地图App中附近地点搜索及聚合标记功能

如何使用配置了ajax搜索的select2 jquery插件实现选择所有功能。?

C#中如何实现百度搜索框的效果