【问题标题】:How do I design a database to store properties, selecting attributes by synonyms如何设计数据库来存储属性,按同义词选择属性
【发布时间】:2011-11-17 06:22:01
【问题描述】:

我正在为房地产应用程序设计一个数据库。事实证明,它比我预期的更复杂(也许我把事情复杂化了)。

问题本质上是由于存在:

  • 同义词 例如:flat、apartment 和 penthouse 可能都指本质上相同类型的房产
  • 属性(不同的属性类型有不同的属性) 例如,公寓可能是底层或顶层等

我最终得到了一个用于不同属性类型的相当(无意)精细的分类树。树节点是属性类型的实际实例。

我想创建一个数据库,这样我不仅可以使用任何同义词,还可以使用属性进行查询。

例如,查询(在伪 SQL 中):

SELECT * from properties where synonym="flat" and attribute IN ('ground floor', 'garden');

应返回位于底层且带花园的公寓|公寓列表。

有人可以帮助我设计数据库模式以允许上述类型的查询吗?

最后但并非最不重要的一点是,我将使用 MySQl 或 PostgreSQL 作为后端数据库,但如果可能的话,我更喜欢这种方法与数据库无关。

【问题讨论】:

  • ". . . flat、apartment 和 penthouse 本质上可能都指的是同一类型的财产" 也可能不是。如果我正在寻找顶层公寓,我不想看到公寓。 (可能。)
  • "一楼有花园。"没有意义,要么什么?

标签: database-design


【解决方案1】:

我会对您的归因方案采取不同的方法。我不会将不同的属性视为同义词,而是将它们视为重叠的,或者更具体地说,是对属性的嵌套描述。这将处理您的业务案例,同时承认 Mike Sherrill 的敏锐观察。

这是一个快速的 ERD 草图:

通过一个非常快速的数据字典:

PROPERTY 是一块不动产。

CATEGORY 是描述性属性的集合。这张表的重点更多是作为属性的组织者,而不是其他任何东西。它可能包括诸如“财产类型”、“所有权结构”、“浴室数量”之类的内容,以及任何其他可能感兴趣的内容。

ATTRIBUTE 是一种特定的兴趣质量。请注意此实体类型的内卷关系。稍后我会处理更多。要点是属性可以更一般或更具体,并且某些属性可以看作是其他属性的细化。

DESCRIPTOR 是 PROPERTY 和与该特定不动产相关联的 ATTRIBUTE 的交集。

那么这应该有什么帮助呢?

关键是属性如何工作。如果您使用嵌套集模型,那么您可以解决或多或少特定的归因和搜索条件。考虑下一个潜在类别及其相关属性的图表:

在本例中,CATEGORY 是“属性类型”。从图中可以看出,该类别中的属性存在层次结构分解。图中的每个框都是 ATTRIBUTE 中的一条记录。包含其他框的框具有子属性。位于另一个盒子内的盒子对其包含盒子有一个 FK,依此类推。

通过这种方式,您可以说“我想找一处顶层公寓”。然后,您可以找到带有指向“Penthouse”属性的相关描述符的 PROPERTY 记录。这很容易。但是,如果您的搜索结果为空怎么办?

这种方法的优势在于,您可以通过说“让我们将归因层次结构提升到下一个比顶层公寓不太具体的东西”来放松您的标准。在我的例子中,那将是“高层”。现在你再次尝试搜索,你可能会有更好的运气。

这样的系统使您能够在每个归因类别中尽可能具体,同时将其他归因类别放宽到足以开始获得搜索命中。这真的是房地产经纪人的工作,不是吗?帮助客户做出必要的妥协以找到最符合他们最重要标准的方案?

处理嵌套集

这种方法唯一棘手的部分是如何处理嵌套集。有很多方法可以做到这一点,其中许多已在其他地方彻底记录。我自己喜欢visitation number 技术,尤其是对于相对静态的数据集。这使得查找某些给定 ATTRIBUTE 或其任何子项的匹配项变得非常容易,而无需在 SQL 中执行任何奇特的操作。

编辑:那么它是如何工作的?

OP 询问您如何处理诸如卧室数量之类的问题以及查询是什么样的?我们再举一个例子来说明:

上面显示了类别“卧室数”的嵌套集。我还在图表中添加了访问次数。请注意访问数字的工作方式,特别注意任何给定属性值的左(绿色)和右(红色)数字包含任何从属属性的左和右访问数字。例如,“2+ Bedrooms”的左右数字分别为 6 和 15。属于“2+ Bedrooms”的每个属性都有在这个范围内的左右数字。

那么您将如何查询具有给定描述符的属性?假设我们要查找所有有两间或​​更多卧室的房产。此类查询的 SQL 可能如下所示:

select P.* 
from PROPERTY P
  inner join DESCRIPTOR D
    on P.id = D.property_id
  inner join ATTRIBUTE A
    on D.attribute_id = A.id
where A.left >= (select X.left from ATTRIBUTE X
                 where X.name = '2+ Bedrooms')
  and A.right <= (select Y.right from ATTRIBUTE Y
                  where Y.name = '2+ Bedrooms')

请注意,上述查询与您实际使用的查询略有不同。例如,您可能会使用其 int 标识键而不是其字符串名称来查找过滤属性。但是,为了清楚起见,我想我会保留它,以便在要点周围清晰,即您通过查找 not 来查找特定的相关属性,而是查找属于您的过滤器的任何相关属性 范围

如果您想过滤多个属性,只需在 where 子句中添加更多子句即可。

【讨论】:

  • 我认为你在正确的道路上(也为漂亮的图表+1) - 但不知何故,我仍然不“明白”我如何将它付诸实践- 即 1. 设计模式 2. 针对该模式运行示例查询。我特别想知道如何将类别用于房间数量(以及物业类型),以及如何在给定的邮政编码中搜索 2 间卧室的顶层公寓?
  • 如果阁楼查询没有返回匹配项,我会发出什么样的 SQL 语句来告诉数据库获取下一级的记录?抱歉听起来很愚蠢,但我想确保我第一次做对。
  • 请参阅我的编辑,了解如何处理卧室数量和 SQL 的外观等问题。至于如何退回到限制较少的搜索,您要做的是查找原始过滤属性,例如“Penthouse”并使用它的 FK 到 ATTRIBUTE 来找到下一个更广泛的属性值,在这种情况下是“ Highrise”,然后您用“Highrise”重复查询,希望您能找到一些匹配项。
  • 感谢您的详细回复。我相信您的答案是正确的,但是我必须阅读很多其他问题,以确保我完全理解您所写的内容(更重要的是),以便我可以将其实施到可行的解决方案中。所以在我接受你的回答之前可能需要一段时间(我可能还得问你一些更“愚蠢”的问题)——我希望你不介意。
  • @JoelBrown 这是一个非常棒的方法,唯一让我不安的是CATEGORIES 在语义上是分离的:您可以设置类别 Property Type ... Land 同时 卧室数量 ... 5+。 .据我了解,它要求您同时查询两个类别(我已经提到过)?如果是这样,那么我们应该向用户显示所有可用的搜索选项(每个事项的类别下拉列表)?
【解决方案2】:

要处理同义词,您可以在包含属性类型静态列表的表和包含同义词的表之间进行多对多查找。这样,一个同义词可以映射到多个属性类型。

例如:

Table:Property Type
1 House
2 Appartment
3 Large House
4 Cave

Table:Synonym
1 house
2 flat
3 dwelling
4 condo
5 mansion

Table:PropertyType-Synonym
1 1 (House is a house
1 3 (House is a dwelling)
2 2 (Appartment is a flat)
2 3 (Appartment is a dwelling)
2 4 (Appartment is a condo)
3 1 (Large House is a house)
3 3 (Large House is a dwelling)
3 5 (Large House is a mansion)
4 3 (Cave is a dwelling)

对于属性,你可以利用一种开放的属性结构。

例如:

Table:Property
1 Apartment F, Field House Gardens
2 123 Alphabet Street, NumberTown

Table:Attribute
1 Is ground floor?
2 Number of bedrooms
3 Has garden?

Table:Property-Attribute-Values
1 1 No
1 2 2
1 3 Yes
2 2 5 
2 3 Yes

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    相关资源
    最近更新 更多