我如何映射标签以标记同义词



我正在构建一个系统,用户将标签与帖子相关联,与此相关。我有一个困扰实施标签同义词的位置

在这里,我有一个名为标签的表

| TagName    |
|------------|
| Python     |
| JavaScript |
| Node       |

我还有另一个称为 tagsynonyms

| SynonymId | SourceTagName | TargetTagName |
|-----------|---------------|---------------|
| 1         | Py            | Python        |
| 2         | Python2       | Python        |

服务器是使用节点实现的,用户将某些标签作为逗号限制的字符串输入:

var input = 'Py,Flask'
var tags = request.tags.split(',');

在这种情况下,用户已输入标签 py ,根据 tagsynonyms 表,应将其映射到标签 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和一个JOIN:

  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注入的精确语法。

更新:这是节点中实现的样子:

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
  });
});

最新更新