在Mysql中构建标记搜索引擎 - 排序问题

时间:2016-08-13 16:43:03

标签: php mysql sorting search-engine

我想基于PHP / MySQL做一个关于视频的简单搜索引擎(比如一个非常简单的Shutterstock)。 所以这是交易。视频包含多个关键字(或标签)。用户在搜索栏中键入一些关键字然后他会获得包含这些关键字的视频列表(按相关性排序)。

我创建了3个Mysql表:

  • 视频:video_id,video_name,video_format等......
  • 标记:tag_id,tag_name
  • video_tag :video_id,tag_id //链接标记和视频的连接表(视频包含1个或多个关键字,1个或多个视频使用关键字)

结果的相关性很重要,这是逻辑:

如果用户在搜索栏中输入:水,木材和自然,结果将如下:

 (1) the videos which associate water, wood and nature
 (2) the videos which associate water and wood
 (3) the videos which associate water and nature
 (4) the videos which associate wood and nature
 (5) the videos which associate water
 (6) the videos which associate wood
 (7) the videos which associate nature

所以我在php中创建了一个算法来构建这种多维数组:

[0] [water, wood, nature]
[1] [water, wood]
[2] [water, nature]
[3] [nature, water]
[4] [wood, nature]
[5] [water]
[6] [wood]
[7] [nature]

接下来,我在MySQL请求中发送此数组,这是我被困住的地方......我的请求是什么:

    SELECT video.video_id,video.video_name, GROUP_CONCAT(tag.tag_name) AS tags

    FROM
        video_tag
        INNER JOIN video
          ON video_tag.video_id = video.video_id
        INNER JOIN tag
          ON tag.tag_id = video_tag.tag_id

    GROUP BY video_id

    HAVING tags LIKE '%water%' AND tags LIKE '%wood%' AND tags LIKE '%nature%.'
    OR tags LIKE '%water%' AND tags LIKE '%wood%'
    OR tags LIKE '%water%' AND tags LIKE '%nature%'
    OR tags LIKE '%wood%' AND tags LIKE '%nature%'
    OR tags LIKE '%water%'
    OR tags LIKE '%wood%'
    OR tags LIKE '%nature%'

但结果的顺序不对。一切都按video_id排序。

video_id            video_name            tags
1                   video 01            wood, keyword4, keyword5, keyword 6, keyword 7
2                   video 02            wood, nature, water, keyword 6
3                   video 03            nature, water, keyword 7

我想要的订单如下:

video_id            video_name            tags
2                   video 02            wood, nature, water, keyword 6
3                   video 03            nature, water, keyword 7
1                   video 01            wood, keyword4, keyword5, keyword 6, keyword 7

在Mysql中是否有办法按请求的“自然”顺序排序结果?我这样做是对的吗?有人已经遇到过这种麻烦并可以帮助我吗? :)

2 个答案:

答案 0 :(得分:1)

首先,您可以将having子句简化为:

having max(tag_name = 'water') > 0 or
       max(tag_name = 'nature') > 0 or
       max(tag_name = 'wood') > 0

换句话说,您不需要处理字符串,只需使用原始标记。

然后,您可以通过这个简单的逻辑接近您想要的东西:

order by ((max(tag_name = 'water') +
          (max(tag_name = 'nature') +
          (max(tag_name = 'wood')
         ) desc

这按不同匹配标记的数量排序。我不确定为什么两个匹配标签的排序会有所不同。

您的订购似乎更喜欢水>木材>自然,所以:

order by ((max(tag_name = 'water') +
          (max(tag_name = 'nature') +
          (max(tag_name = 'wood') 
         ) desc,
         max(tag_name = 'water') desc,
         max(tag_name = 'nature') desc,
         max(tag_name = 'wood) desc

请注意,在数值上下文中,布尔值被视为整数,“1”表示true,“0”表示false。这就是max()+适用于这些查询的原因。

答案 1 :(得分:1)

谢谢。有了你的主张,我终于意识到自己过于复杂。不需要多维数组或组合逻辑......

以下是我找到的解决方案:

SELECT DISTINCT video.video_name, GROUP_CONCAT(tag.tag_name) AS tags

FROM
    video_tag
    INNER JOIN video
      ON video_tag.video_id = video.video_id
    INNER JOIN tag
      ON tag.tag_id = video_tag.tag_id

WHERE tag.tag_name= 'wood' OR tag.tag_name = 'nature' OR tag.tag_name = 'corporate'

GROUP BY video_id
ORDER BY COUNT(*) DESC;

就像那样,我选择与所需标签链接的所有视频。然后我只计算一个视频有多少标签...然后用这个数字排序......最后,我的麻烦很容易。

对不起因干扰;)