在 Mysql 中构建标签搜索引擎 - 排序有问题
Building a Tag Search Engine in Mysql - Trouble with sorting
我想基于 PHP/MySQL 做一个关于视频的简单搜索引擎(比如一个非常简单的 Shutterstock)。
所以这是交易。一个视频有多个关键字(或标签)。用户在搜索栏中输入一些关键字,然后他会得到包含这些关键字的视频列表(按相关性排序)。
我创建了 3 Mysql tables :
- 视频 : video_id, video_name, video_format, 等等...
- 标签 : tag_id, tag_name
- video_tag : video_id, tag_id // 加入 table 其中 link 标签和视频(因为一个视频有 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 中有没有办法获取按请求的 "natural" 顺序排序的结果?我这样做是对的吗?有人已经遇到过这种麻烦并且可以帮助我吗? :)
首先,您可以将 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”表示真,“0”表示假。这就是 max()
和 +
适用于这些查询的原因。
谢谢。有了你的提议,我终于意识到我自己太复杂了。不需要多维数组或组合逻辑...
这是我找到的解决方案:
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;
就这样,我 select 所有视频都链接了所需的标签。然后我就统计一个视频有多少个tag。。。然后按这个数排序。。。最后,我的麻烦就很简单了。
抱歉打扰了;)
我想基于 PHP/MySQL 做一个关于视频的简单搜索引擎(比如一个非常简单的 Shutterstock)。 所以这是交易。一个视频有多个关键字(或标签)。用户在搜索栏中输入一些关键字,然后他会得到包含这些关键字的视频列表(按相关性排序)。
我创建了 3 Mysql tables :
- 视频 : video_id, video_name, video_format, 等等...
- 标签 : tag_id, tag_name
- video_tag : video_id, tag_id // 加入 table 其中 link 标签和视频(因为一个视频有 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 中有没有办法获取按请求的 "natural" 顺序排序的结果?我这样做是对的吗?有人已经遇到过这种麻烦并且可以帮助我吗? :)
首先,您可以将 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”表示真,“0”表示假。这就是 max()
和 +
适用于这些查询的原因。
谢谢。有了你的提议,我终于意识到我自己太复杂了。不需要多维数组或组合逻辑...
这是我找到的解决方案:
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;
就这样,我 select 所有视频都链接了所需的标签。然后我就统计一个视频有多少个tag。。。然后按这个数排序。。。最后,我的麻烦就很简单了。
抱歉打扰了;)