【问题标题】:Tagging hierarchy and search标记层次结构和搜索
【发布时间】:2013-07-24 18:37:25
【问题描述】:

我正在尝试创建一个可以搜索的相对简单的分层标记系统。这是它现在的工作方式,这是 MySQL 表结构:

--------------------------------------------
id  | tag         | parentID | topParentID |
--------------------------------------------
1   | Boston      | NULL     | NULL        |
--------------------------------------------
2   | Events      | 1        | 1           |
--------------------------------------------
3   | June 30th   | 2        | 1           |
--------------------------------------------
4   | NYC         | NULL     | NULL        |
--------------------------------------------
5   | Attractions | 4        | 4           |
--------------------------------------------

因此,如果用户在搜索栏中输入波士顿,他们将收到建议“波士顿活动”和“波士顿活动 6 月 30 日”。同样,如果他们在搜索栏中输入 NYC,他们将收到“NYC Attractions”作为建议。

此外,如果有人在搜索栏中输入“事件”,他们会收到“波士顿事件”的建议,或者如果他们输入 6 月 30 日,他们会收到“波士顿事件 6 月 30 日”的建议

我弄乱了代码来执行此操作,我绝对可以将查询字符串分解为关键字,然后在标签表中搜索每个关键字并返回匹配项,但我还没有找到返回完整的正确方法以我上面提到的格式标记字符串。

【问题讨论】:

  • 为什么事件的 parentID=topParentID?我认为,对于 2 级元素,topParentID 必须为 NULL。
  • @user4035 我想无论哪种方式都是可能的。我不完全确定 topParentID 是否完全必要。无论如何,我试图回答比这更大的问题。

标签: php mysql search tagging


【解决方案1】:

嗯,你可以加入同一张桌子两次。假设,我们有 $id - 当前标签的 id:

SELECT
    tags.id,
    tags.tag,
    parent_tags.id,
    parent_tags.tag,
    parent2_tags.id,
    parent2_tags.tag,
FROM
    tags
INNER JOIN
    tags AS parent_tags
ON
    tags.parentID = parent_tags.id
INNER JOIN
    tags AS parent2_tags
ON
    tags.topParentID = parent2_tags.id
WHERE
    tags.id=$id

但是由于你表中的数据不正确,它会给父母和祖父母两次:parent.id = parent2.id

实际上,这是一个非常原始的解决方案,只允许在 1 个请求中显示 2 级层次结构。如果您想实现任何级别,请阅读堆栈上的嵌套集。还有一本很棒的书:Joe Celko 撰写的“聪明人用 SQL 中的树和层次结构”

【讨论】:

  • 我宁愿不把它限制在两个级别。我也去看看书。谢谢!
  • 原则上,您可以使用此模型来存储有关无限级别数据的信息,使用父级的父级等。但是您需要 1 个请求来检索任何级别的子级。因此,对于 n 个级别,您将需要 n 个请求,这很慢。
  • 有什么可以做的...我意识到这不是真正的 SQL 代码...SELECT (SELECT parentID - 1 UNTIL id = topParentID) FROM tags WHERE...
  • @Ben 是的,您必须编写一个递归过程。我不知道,是否可以使用纯 SQL,或者您必须在 php 中为每个级别发出 n 个请求。
  • @Ben 请考虑对您的问题提出一个接受答案的要求。当然,我无法为您编写整个嵌套集合的实现。
【解决方案2】:

我认为您可以删除 topParentID 列并添加一个称为“级别”的列(波士顿将有级别 0,事件级别 1,6 月 30 日级别 2)。 因此,您按此级别列冷排序并内爆这些值,这样您就会得到您想要的东西。

你可以在没有 level 列的情况下做到这一点,但我认为在 php 方面会做更多的工作。

【讨论】:

  • 所以...有人搜索波士顿(级别 0),查询会返回波士顿以下也与波士顿相关的级别?
  • 我不认为你可以用 mysql 做一个递归过程。您可以: A) 将逻辑放在 php 上。 B)完全改变你存储树的方式,这样即使没有递归过程你也可以找到东西。这是一个链接,您可以在 sql 中找到很多关于树的信息。查看幻灯片 48 和 77。slideshare.net/billkarwin/sql-antipatterns-strike-back
猜你喜欢
  • 2011-05-26
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 2010-09-12
  • 2015-01-09
  • 1970-01-01
相关资源
最近更新 更多