如何将标签映射到标签同义词?

我正在构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 }); });