如何将标签映射到标签同义词?
我正在构build一个系统,用户将标签与post相关联,与SO不同。 我有一个麻烦实现标签同义词的位置 。
在这里我有一个名为Tags的表格:
| TagName | |------------| | Python | | JavaScript | | Node |
而我又有一个叫做TagSynonyms的人 :
| SynonymId | SourceTagName | TargetTagName | |-----------|---------------|---------------| | 1 | Py | Python | | 2 | Python2 | Python |
服务器使用Node实现,用户input一些标签作为逗号分隔的string:
var input = 'Py,Flask' var tags = request.tags.split(',');
在这种情况下,用户已经input了标签Py ,根据TagSynonyms表,它应该被映射到标签Python 。 第二个标签, Flask没有同义词,应该保持不变。
我设法使用命令式的代码来实现这个function:
tags.forEach(function (tag) { connection.query('SELECT TargetTagName FROM TagSynonyms WHERE SourceTagName = ?', tag, function(err, rows) { if (rows.length !== 0) { console.log(rows[0].TargetTagName); } else { console.log(tag); } }); });
在这里,用户input
['Py','Flask']
导致以下输出
Python Flask
我想要做的是,推迟这个逻辑到数据库引擎,因为我认为使用循环是一种代码味道。 我也认为数据库引擎会更高性能。 什么是适当的查询来做到这一点?
你需要一个UNION
和一个连接:
select TagName from Tags where TagName in (?,?,?,...) union select TagName from Tags join TagSynonyms on Tags.TagName = TagSynonyms.TargetTagName where TagSynonyms.SourceTagName in (?,?,?,...)
请注意, union
可能会很慢,因为它会尝试删除重复项。 如果是这种情况,请使用union all
并删除应用程序代码中的重复项。
(?,?,?,...)
代表input值列表; 检查您的数据库驱动程序文档以了解您需要使用的确切语法以避免SQL注入。
更新:下面是在Node中的实现:
var query = 'SELECT TagName \ FROM Tags \ WHERE TagName IN (?) \ UNION \ SELECT TagName \ FROM Tags \ JOIN TagSynonyms \ ON Tags.TagName = TagSynonyms.TargetTagName \ WHERE TagSynonyms.SourceTagName IN (?)' connection.query(query, [tags, tags], function(err, rows) { tags = rows.map(function(row) { return row.TagName }); });