处理标签

时间:2012-10-06 14:02:04

标签: php mysql database-design autocomplete tagging

我们计划使用类似于此网站上实施的标记系统。

我们有实际的标记前端,自动完成等工作。

但我对于在后端处理它的最佳方法感到困惑。

基本上,当我们在后端获得标签时,我们最终得到一个看起来像这样的数组:

array(
  array(
    'value' => 1,
    'label' => 'First Tag'
  ),
  array(
    'value' => 2,
    'label' => 'Second Tag'
  ),
  array(
    'value' => 'Third Tag',
    'label' => 'Third Tag'
  ),
  array(
    'value' => 3,
    'label' => 'Fourth Tag'
  ),
)

标记插件在自动填充时也通过ajax接收相同的数组格式json_encode()'d,它显示标签,并存储id以便它可以将其发回。

因此,包含值123的标记是从自动填充中选择的标记。
值为Third Tag的标记是未从自动填充中选择的标记,可能已经存在,也可能尚未存在于数据库中但已手动输入。

现在有一个变化,用户实际上可以创建一个恰好是数字的标签,因此

array(
  'value' => 3,
  'label' => 3
)

可以通过,但尚未存在,所以我们不能只假设如果value是一个int,那么它已经存在。

所以,这个问题的第一部分是,我如何管理这个,所以我最终没有重复的标签?

我目前的做法是,当标记插件通过自动完成请求标记时,我发回一个数组,如

(term ='pin')

array(
  array(
    'value' => '||1',
    'label' => 'pink'
  ),
  array(
    'value' => '||4',
    'label' => 'pin cushion'
  )
)

然后在后端假设任何标签的值都以||开头来自自动完成并且已经存在。

然后, 我们在数据库中查询所有标签, 对于其余的标记,我们检查以确定value是否存在数组的label键,如果是,我们只是将其保留原样,如果不是我们创建它,然后我们使用原始数组中的新id切换值。

但是这对我来说很难,这意味着我们正在使用填充项目(||)必须有更优雅的方式来做这件事吗?

问题的下一部分是,实际上将这些标签链接到一个项目。 这更多是在本网站编辑问题的背景下,

某些标签已与问题相关联。你如何处理它,以便你最终不会在问题上重复标记引用?

到目前为止我看到两个选项: 从问题中删除所有标签链接,然后再将它们全部插入。(2个查询)

在数据库中查询与问题相关的所有标签,在数组上循环从数组中删除这些标签,然后插入余数。 (2个查询)

两种方法都比另一方好吗?还是有第三个版本?

1 个答案:

答案 0 :(得分:2)

通过在相关字段上添加唯一约束,可以在数据库级别解决任何类型的重复键问题。所有代码与代码的交互都应使用文本标签完成,该标签应作为标记的唯一标识符。任何类型的数字ID都不会为应用程序本身提供任何用途,因此不需要从存储库层后面查看。这也可以解决现有/新标签的差异......有效地应用程序无关紧要,它将标签视为持久化的值对象,而不是担心任何类型的实体样式生命周期。在标记与文章关联的存储库调用中,如果标记尚不存在,则创建标记。在执行标记查询所需的JOIN(并且实际上不在其他任何地方)时,ID将主要有益于性能,这也是应用程序在进行连接的存储库之外不应关心的事情。

更新标签(包括删除标签)最安全,最简单的方法是抛出现有标签并编写新标签。这确保持久状态完全一致地匹配UI输入,并且实际上这不会是昂贵的操作,也不会经常执行足够的关注(尽管通过简单的程序检查来查看是否需要更新将有助于防止不必要的写作)。这是2个应该包含在事务中的查询,并且可以一起批处理,特别是DELETE应该非常便宜,只要适当的索引到位,所以它不是你需要担心的那种多重查询。

如果由于某些奇怪的原因你过分担心最小化数据库的工作,你可以预先存储一个版本的标签,然后再存储适合delta的查询,但这更加脆弱,并且可能还引入了许多复杂的并发问题。