Java 任命和行项目

Java 任命和行项目,java,google-app-engine,database-design,appointment,Java,Google App Engine,Database Design,Appointment,我正在构建一个管理应用程序来帮助管理我的移动汽车公司(希望还有其他公司)。我正在努力弄清楚如何对一些数据进行建模 这个问题与我之前发布的一个问题有关,但我复制了以下相关信息: 在此应用程序中,有“约会”和“行项目”的概念 预约是指员工为提供服务而需要去的地方和时间 行项目是服务、费用或折扣及其相关信息。可能进入约会的行项目示例: Name: Price: Commission: Time estimate Full Detail, Reg

我正在构建一个管理应用程序来帮助管理我的移动汽车公司(希望还有其他公司)。我正在努力弄清楚如何对一些数据进行建模

这个问题与我之前发布的一个问题有关,但我复制了以下相关信息:

在此应用程序中,有“约会”和“行项目”的概念

预约是指员工为提供服务而需要去的地方和时间

行项目是服务、费用或折扣及其相关信息。可能进入约会的行项目示例:

Name: Price: Commission: Time estimate Full Detail, Regular Size: 160 75 3.5 hours $10 Off Full Detail Coupon: -10 0 0 hours Premium Detail: 220 110 4.5 hours Derived totals(not a line item): $370 $185 8.0 hours 这种结构的一个普遍问题是它很复杂,我甚至不确定将一个行项目与多个约会匹配是否合适。如果行项目只能是一个约会的一部分,那么我实际上可以在每个约会中放置一个行项目列表,当我得到约会时,我已经得到了行项目

一个更具体的问题是,我正在使用google app engine,如果我想查询一组约会及其关联的行项目,我必须首先查询约会集,然后使用IN操作符对行项目执行第二次查询,以测试行项目的约会键是否属于上次查询返回的约会键集。如果我有30多个键需要切分查询,则第二个查询将失败。我可以对数据进行反规范化,以避免这种复杂而广泛的读取查询,而且我可能无论如何都必须在某种程度上进行反规范化,但我宁愿在适当的情况下避免复杂性

我的问题是,这种情况通常是如何建模的?是否适合将一个行项目与多个约会配对,或者简单地将每个约会的行项目分成单独的行项目,例如“两天工作的前半部分”和“两天工作的后半部分”。类似的成功应用程序是如何做到这一点的?在这种情况下,经验法则是什么?哪些实现的问题更少


谢谢

这类问题的通常解决方案是规范化模型,即

标准化形式的模型将有第三个表,其中引用了
约会
行项目
行:

Appointment
 start_time
 ...

Line_Item
 name
 price
 ...

Appointment_Line_Item
 appointment_key
 line_item_key
然而,有一个问题!因为您使用的是Google App Engine,而且他们的数据存储非常有限,并且大部分需要非规范化

您建议使用类似列表的字段。这是一个可能的使用,但它是非常困难的索引。在数据库中每行的列表中搜索一个键(约会键)。我提出两种可能性:

  • 重复的
    行项目

    Line_Item
     appointment_key
     name
     price
     finished
     ...
    
    当员工完成或未完成项目时,
    行项目
    应具有
    finished
    状态。如果员工尚未完成所有行项目,请将其标记为未完成,创建新约会并复制所有未完成的项目。您可以在所有
    行项目的
    约会键
    字段上建立索引,这是一件好事。但是,重复数据可能是一个问题

  • 行项目的动态字段

    Line_Item
     duplicate_key
     appointment_key
     name
     price
     finished
     ...
    
    行项目
    创建一个新字段,
    复制项
    ,该字段指向另一个
    行项目
    或null(保留此项!)。Null表示
    行项目
    是原始项目,任何其他值表示此
    行项目
    是字段指向的
    行项目
    的副本。标记为重复项的
    行项目
    的所有字段继承原始
    行项目
    的字段,但
    约会键
    除外:因此占用的存储空间较少。此外,此解决方案还应为约会键编制索引,以加快查找时间。这需要对每个重复的
    行项目
    进行一次额外的查询,这可能是一个问题


  • 现在,这是一个明确的选择:要么提高速度,要么提高存储。我会选择第一种,因为它降低了模型的复杂性,而且存储在现代系统中从来都不是问题。较低的复杂性通常意味着更少的bug和更少的开发/测试成本,这证明了存储需求的成本是合理的。

    您建议的方法可以很好地工作;您可以将行项目的“约会\关键\列表”建模为列表属性,它将按照您的预期工作。您不必使用IN运算符-这是为了将数据存储中的单个值与您拥有的键列表(例如,“WHERE datastore_column IN('a'、'b'、'c')进行匹配),而使用相反的运算符-将单个值与数据存储中的列表进行匹配

    不过,我建议,相反的方法可能更适合您的任务:让每个约会都有一个行项目键列表。操作方式大致相同,但要检索约会上的所有数据,您可以先获取约会,然后使用约会实体中的键对行项目进行批量获取。如果您知道由于是预约的钥匙,因此您根本不需要进行任何查询

    我一直在试图向Pindatjuh解释为什么查询列表属性的效率不低于单值属性,但显然需要更详细的描述,因此无需进一步讨论,这里是

    应用程序引擎数据存储索引简介 尽管Python和Java为数据存储提供了各种高级接口,但数据存储本身讲的是一种较低级别的抽象,称为实体

  • 唯一主键
  • (名称、值)对的列表
  • 主键是您已经熟悉的数据存储键。(名称、值)对的列表是应用程序引擎对数据i的表示
    Line_Item
     duplicate_key
     appointment_key
     name
     price
     finished
     ...
    
    a_string = "Hello, world"
    an_int = 123
    
    [('a_string', 'Hello, world'), ('an_int', 123)]
    
    a_string = "Hello, world"
    an_int = 123
    a_list_of_ints = [42, 314, 9]
    
    [('a_string', 'Hello, world'), ('an_int', 123), ('a_list_of_ints', 42), ('a_list_of_ints', 314), ('a_list_of_ints', 9)]
    
    ('Hello, world', 123, a_key)
    
    (123, 42, a_key)
    (123, 314, a_key)
    (123, 9, a_key)