问题 允许一个类别拥有多个父母是否有意义?还有替代品吗?


简短的问题: 如何管理出现在多个类别下的产品类别?完全这样做是不好的做法?

背景资料: 我们有一个产品数据库,其类别如下:

Products

  -Arts and Crafts Supplies
    -Glue
    -Paper Clips
    -Construction Paper


  -Office Supplies
    -Glue
    -Paper Clips

请注意,胶水和纸夹分配给两个类别。 虽然它们出现在这个类别树的两个不同位置, 它们在数据库中具有相同的类别ID。为什么?两个原因:

  1. 为类别分配属性 - 例如,回形针可以具有重量,材料,颜色等。
  2. 分配到胶水类别的产品显示在工艺品和办公用品下。这是预期的 - 它们与数据库中的实际类别ID相同。

这允许我们管理单个类别及其属性和分配的产品,但将其放置在类别树中的多个位置。

我们正在使用 嵌套集模型,所以我们用来支持这个的db结构是:

Category
----------
CategoryID
CategoryName


CategoryTree
------------
CategoryTreeID
CategoryID
Lft
Rgt

因此,Category和CategoryTree之间存在1:M,因为类别树中可能存在给定类别的多个实例。

有没有更简单的方法来模拟这个允许产品类别在多个类别下显示?


12928
2017-10-01 15:25


起源

+1有趣的问题 - KLE


答案:


只要这是真的,我认为这没有任何问题 所有 胶水适用于两种办公用品  工艺用品。


5
2017-10-01 15:32



如果不是怎么办?喜欢小孩胶棒。这是唯一的艺术和手工艺品。同意,你真的被困在创建一个单独的类别?有什么建议吗?我很难想象这个类别中的每个产品都适用于这两个地方的情况。我不确定一个人是否存在。 - Cory House
使用您拥有的模型,然后是,您需要创建一个单独的类别。我认为,您的两个选项是将显示分类与分类分类(使用其他属性)分开,或者使您的类别树成为从根到叶的不同路径,然后将产品与这些树相关联。 (虽然知道它的可扩展性,但我还没有完全考虑过) - Jacob G
雅各布,我应该在回答科里之前阅读你的答案,因为你涵盖了大部分相同的理由,而且往往更经济。 - Steven Sudit


你有什么是一个好方法,虽然为什么不像这样简化第二个表:

类别

ID 名称

子类别

ID 类别ID SubCategoryID

虽然将来我会注意在两个根类别之间共享子类别。有时最好创建一个独特的产品分类以保持一致性,这样更容易为您管理,并且可能更容易为客户导航。否则,你有一个问题,如果你在胶水页面上来自办公用品,那么你是否也展示了另一条路径?如果没有,您将有两个相同的页面,路径除外,这是SEO的问题。如果你这样做,那么用户可能会感到困惑。


3
2017-10-01 15:36



优点eulerfx。我们遇到了这个问题,这是我提出这个问题的众多原因之一。 - Cory House
@eulerfx,您能否详细说明如何让两个页面具有相同内容,除了层次结构中的不同父级可能导致SEO问题? - Steven Sudit
我刚刚注意到你的子类表建议正在描述邻接模型。虽然我同意最初理解它是简单的结构并且使插入和更新变得容易,但嵌套集模型的性能远远优于选择 - 在产品类别结构上,它是我们流量的99%以上。另外,查询嵌套集要简单得多。邻接模型需要树中每个级别的连接,这在大树上变得难以处理。 - Cory House
MS SQL Server具有CTE,它允许有效的递归,我知道Oracle至少具有强大的功能,所以不要根据可能的性能问题找出一个好的解决方案。我还要补充一点,显示目录是一个原型案例,在高负载站点上可能需要缓存网页本身。 - Steven Sudit
好点Steven,虽然有问题的应用程序是关于MySQL的,我知道没有等效的递归功能。老实说,它是查询嵌套集的简单性和可扩展性,我发现它比邻接模型更具吸引力。 - Cory House


其中最着名的例子是Google Mail,其中分类以这种方式完成。谷歌以其产品的可用性而闻名......

我相信其他单词比“父”单词更可取,实际上只表示XToOne关系......

也许你可以这样说 Product 尽可能多 Categories,所以关系将是ManyToMany。只有显示器才会以类别开头才能到达产品......


这将突出显示一个问题:如果您不限制类别数量,并且您显示带有子类别的类别等等,您最终可能会:

  • 一个庞大的类别和产品列表,有许多重复
  • 深度很大(可能不可读)

有趣的部分是突出问题,然后想象一个对最终用户来说很好的解决方案。


2
2017-10-01 15:28





一个类别可能需要多个父母。但是,无论您在哪个父级中找到类别,其子类别应保持不变。

我已经看到了真正实现这种逻辑并且工作正常的系统。

编辑

为了回答你的问题,我认为我所建议的模型并不像你想象的那样具有限制性。基本上,树的给定分支可以在多个父分支下找到,但是无论在哪里找到它,它都具有相同的子分支。没有任何关于这个可以阻止你挑选一个分支的一些孩子,并使他们成为另一个分支的孩子。

因此,例如,您可以在办公用品和爱好用品下添加胶水类别,如果您在胶水下添加“Crazy Glue(Suppository Edition)”,它将显示在两者中。如果您有可能按逻辑分组在一起但需要按其用途分开的项目,您仍然可以这样做。你可能会把粘液和粘贴物放在业余爱好粘合剂的范畴之下,它属于业余爱好根,但不属于办公室根部。或者你可以这样做并同时拥有一个由买家内部使用的组合类别。你不能做的是忘记在所有相关类别中添加新类型的胶水,只要它在商业模型本体中的任何位置添加它。

简而言之,您在此限制中损失很少,但获得一些结构以帮助避免必须单独管理每个项目的问题。

编辑

假设我已经为模型本身做了一个令人信服的案例,那么仍然存在实施问题。有很多选择,但这是一种方法:

有一个CatalogItem表,其中包含合成主键,标签,可选描述/详细信息文本以及可选SKU(或等效文件)。然后,您有一个多对多的CatalogItemJoin,其中包含子ID和父ID,两侧都限制为CatalogItemTable。

显示为父项的项目是类别,因此它不应具有SKU。仅作为子项出现的项目是产品,因此它应具有SKU。任何物品都有一个以上的父母是好的;这只意味着它属于多个类别。同样,每个父母的多个孩子也没有问题;这将是一个典型的案例,其中包含一些产品。但是,给定一个类别的ID,无论父类如何引导您,其子级都将是相同的。另一个限制是你要避免循环。


1
2017-10-01 15:27



谢谢史蒂文 - 你能澄清为什么子类别应保持不变吗?在我的例子中,结构不需要它。将建筑用纸放在办公用品之下是没有意义的。因此,解决方案是将产品分配到类别树中的某个位置而不是类别ID,这使得管理更加有效,因为我必须将产品分配给树中胶水类别的两个实例,但确实提供了更多灵活性。 - Cory House
科里,我添加了一节试图回答你的问题。可以? - Steven Sudit