如何将标签映射到标签同义词?
How do I map tags to tag synonyms?
我正在构建一个系统,用户可以在其中将标签与帖子相关联,这与 SO 没有什么不同。我有点麻烦实施 tag synonyms.
这里我有一个 table 叫做 Tags:
| TagName |
|------------|
| Python |
| JavaScript |
| Node |
我还有一个叫做 TagSynonyms:
| SynonymId | SourceTagName | TargetTagName |
|-----------|---------------|---------------|
| 1 | Py | Python |
| 2 | Python2 | Python |
服务器使用 Node 实现,用户输入一些标记作为逗号分隔的字符串:
var input = 'Py,Flask'
var tags = request.tags.split(',');
在这种情况下,用户输入了标签 Py,根据 TagSynonyms table,应该是映射到标签 Python。第二个标签 Flask 没有同义词,应该保持不变。
我设法使用命令式代码实现了此功能:
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);
}
});
});
此处,用户输入
['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
并删除应用程序代码中的重复项。
(?,?,?,...)
代表输入值列表;检查您的数据库驱动程序文档,了解您需要使用以避免 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
});
});
我正在构建一个系统,用户可以在其中将标签与帖子相关联,这与 SO 没有什么不同。我有点麻烦实施 tag synonyms.
这里我有一个 table 叫做 Tags:
| TagName |
|------------|
| Python |
| JavaScript |
| Node |
我还有一个叫做 TagSynonyms:
| SynonymId | SourceTagName | TargetTagName |
|-----------|---------------|---------------|
| 1 | Py | Python |
| 2 | Python2 | Python |
服务器使用 Node 实现,用户输入一些标记作为逗号分隔的字符串:
var input = 'Py,Flask'
var tags = request.tags.split(',');
在这种情况下,用户输入了标签 Py,根据 TagSynonyms table,应该是映射到标签 Python。第二个标签 Flask 没有同义词,应该保持不变。
我设法使用命令式代码实现了此功能:
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);
}
});
});
此处,用户输入
['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
并删除应用程序代码中的重复项。
(?,?,?,...)
代表输入值列表;检查您的数据库驱动程序文档,了解您需要使用以避免 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
});
});