2012-02-04 55 views
0

嗨我有一个大问题,一个MYSQL搜索。 我的数据库表看起来像这样:如何让MYSQL搜索最少3个关键字匹配?

+------+----------+------+ 
| id | keywords | file | 
+------+----------+------+ 

在关键词有与昏迷分隔每个条目的关键字。 (关键词1,关键词......)。

在PHP数组中列出了一些关键字(5-10)。 而我的搜索必须获得所有关键字至少3的数据库条目。 它不需要得到所有这些单词!但它不能工作,只有一个。

有人可以帮我解决这个问题吗?我不知道如何做到这一点。

+0

那么什么是你的其他的表结构看起来就像你正在寻找对抗......或者是这样的吧,你只是用一个字符串来比较。如果是这样,关键字上下文设计不佳。 – DRapp 2012-02-04 17:11:30

+0

还没有其他表。我必须在现场搜索:关键字。 – Svetoslav 2012-02-04 17:14:53

+4

@Svetlio:表格结构是您的选择吗?你是如何使用逗号分隔值列来的?如果你看过这将是良好[规范化](http://en.wikipedia.org/wiki/Database_normalization),并在关系表中存储逗号分隔值的问题:是存储一个逗号数据库中的列分隔列表真那坏?](http://stackoverflow.com/questions/3653462/is-storing-a-comma-separated-list-in-a-database-column-really-that-bad) – 2012-02-04 17:34:11

回答

2

这是一个挑战。暴力方法是在一个带有计数的子查询中使用UNION。

例如,

select id, file, count(*) from 
    (select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword1, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword2, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword3, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword4, keywords) 
    .... MORE UNION ALL ....) as files 
group by id, file 
having count(*) >= 3 

更有效,你可以有关键字和ID,一个关键字/每行ID组合一个单独的表。这将消除通配符搜索并使查询更有效。

接下来的步骤是去ElasticSearch之类的东西,并过滤结果的分数。

+0

所以,如果你搜索关键字'男人',它也会计算关键字'女人','男人','鬃毛'和'许多'...更多 – 2012-02-04 17:21:41

+0

没有说这是一个很好的解决方案。只是它会起作用。该解决方案将是确保每一个关键字后缀有一个“”这样的关键词可能是‘女人,男人,男子汉气概,鬃毛’,然后修改查询每次放在后面的逗号。 – 2012-02-04 17:28:19

+0

是的。你也可以使用'FIND_IN_SET()'函数来识别逗号分隔值。但是,通过按照您的建议制作多对多表格来正常化结构**是正确的方法。所有其他人都是诡计。 – 2012-02-04 17:29:57

0

如果你有这样的设置:

表文件:

+------+-------+ 
| id | file | 
+------+-------+ 
| 1000 | foo | 
| 1001 | bar | 
+------+-------+ 

表关键字:

​​

表filekeywords:

+----+--------+--------+ 
| id | fileid | wordid | 
+----+--------+--------+ 
| 1 | 1000 | 9  | 
| 2 | 1000 | 10  | 
| 3 | 1001 | 10  | 
+----+--------+--------+ 

你可以找到关键字的文件loremipsumdolor这样的:

SELECT COUNT(DISTINCT(k.word)), f.* 
FROM files f 
INNER JOIN filekeywords fk 
    ON fk.fileid = f.id 
INNER JOIN keywords k 
    ON k.id = fk.wordid 
WHERE k.word in ('lorem', 'ipsum', 'dolor') 
GROUP BY f.id 
HAVING COUNT(DISTINCT(k.word)) >= 3