如何在BreezeMongo中使用导航属性

时间:2014-12-10 14:40:49

标签: node.js mongodb breeze

目前,我有2个实体医院和患者有一对多关系,我为它创建了元数据:

function addHospital() {
            addType({
                name: 'Hospital',
                autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity,
                dataProperties: {
                    _id: { type: ID },
                    hospitalID: { type: ID },
                    name: { max: 100 },
                    shortName: { max: 100 },
                    description: { max: 255 },
                    otherInfo: { max: 255 },
                    createdDate: { type: DATE },
                    updatedDate: { type: DATE },
                    createBy: { type: ID },
                    updateBy: { type: ID },
                    stastusID: { type: LUID }
                    ////,patients: {complex:'Patient', hasMany:true}
                },

                navigationProperties: {
                    patients: { type: 'Patient', hasMany: true },
                    //hospitalPatientMap: { type: 'HospitalPatientMap', hasMany: true },
                }
            });
        }

        function addPatient() {
            addType({
                name: 'Patient',
                autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity,
                dataProperties: {
                    _id: { type: ID },
                    patientID: { type: ID },
                    firstName: { max: 100 },
                    lastName: { max: 100 },
                    middleName: { max: 255 },
                    hospitalID: { type: ID, required: true },
                    mrn: { max: 255 },
                    dateOfBirth: { type: DATE },
                    otherInfo: { max: 255 },
                    createdDate: { type: DATE },
                    updatedDate: { type: DATE },
                    createBy: { type: ID },
                    updateBy: { type: ID },
                    stastusID: { type: LUID }
                },
            });
        }

他们可以正确地使用Nodejs / MongoDB / Breeze进行CRUD,但似乎没有为Hospital实现navigationProperties。 即:我的患者确实患有与医院相关的HospitalID: enter image description here

我试图扩展('patiens')

EntityQuery.from('Hospital').expand('patients')
            .toType('Hospital')
            .using(this.manager).execute()
            .then(querySucceeded).catch(self._queryFailed);

但它会抛出BreezeMongo不支持展开的错误 enter image description here

实际上,我可以像这样得到住院患者的病人:

EntityQuery.from('Patient')
          .where('hospitalID', 'eq', hospitalID).using(this.manager).execute()
            .then(success)
            .catch(queryFailed);

但是这种方式并不好,我们每次想要使用时都要调用获取相对实体。

是否有另一种方法可以将navigationProperites加载到实体中(类似于预先加载)?

2 个答案:

答案 0 :(得分:0)

没有相当于微风"扩展" Mongo中的语法。即Mongo中没有任何关系联接。因此,breeze没有简单的方法来执行这样的查询。

通常,如果您的数据在概念上包含在其他数据中,那么标准的NoSQL'建议你将它作为一个包含关系建模。即使患者' a'收集属性'每个医院'并以这种方式存储您的数据。

然后,这个属性将在微风中建模为一个复杂的数组' dataProperty命名为'患者'的医院'实体类型(您在上面的示例中已注释掉 - 略有修改)。 (下面的语法没有被检查过,但是它很接近,并且没有使用MetadataHelper代码)。

,patients: { complexTypeName:'Patient', isScalar: false  }

在这种情况下,无论何时您向医院询问患者'也将自动降下来。

您还需要为您的患者建模'键入一个微风ComplexType而不是EntityType。 ComplexTypes在概念上是不同的,因为它们没有密钥,实体之间永远不会共享实例。此概念直接映射到Mongo集合属性。

在Breeze.js.samples GitHub repo中查看Zza示例中的元数据表示。这是一个有这种关系的Mongo样本。

就个人而言,如果Mongo要增加对某种关系查询运算符的支持,我会很喜欢它,但总的来说,在Mongo社区中,这被认为是一个不起作用,因为这种形式的查询必然会很多慢得多。

答案 1 :(得分:0)

在NoSQL数据库中建模关系是一件棘手的事情。大多数人,如MongoDb,不支持关系。

有时建模很简单,因为您知道您希望聚合嵌入式实体(例如,带有嵌套OrderDetails的Order)。 Jay说,这样的对象最好用Breeze with ComplexTypes建模。

但你无法在任何地方这样做,或者你有一个叫做数据库的巨型聚合: - )

当相关实体不是聚合的一部分时(例如,客户和订单是相关的,单独的聚合),大多数人都会尝试分割差异。他们将对客户中最常用的值进行反规范化并将其复制到订单中。这样,我们通常可以避免额外的服务器之旅,以获得订单的相关客户...或至少推迟该旅行。

当然要做到这一点,你必须知道如何消费秩序。您想将正确的东西复制到订单。

这意味着,与使用关系数据库时相比,您将花费更多时间来定制MongoDb到客户端工作流场景。

由于您的客户要求会随着时间的推移而发生变化,因此您需要持续施加压力来重新塑造NoSQL数据库。随着岁月的流逝,你会感到遗憾。 IMO这是NoSQL最关键的负面因素......而且还没有充分讨论,因为大多数NoSQL项目都是如此年轻而人们无法展望未来。

走开我的肥皂盒......我们对你有什么建议?

可能有一个优势,就是Jay正在谈论的复杂类型和导航属性。让我解释订单和客户。

我可能会将Customer的一部分归一化为一个嵌套对象。在breeze客户端上,我有一个customerInfo属性,它返回一个CustomerInfo复杂类型,其中包含客户的companyName以及我通常在订单列表中显示的任何其他内容。

然后我有Order.CustomerId属性作为Order.Customer导航属性的FK。当我检索订单时,这可能是空的。但是它可用,所以我稍后可以打电话给order.entityAspect.loadNavigationProperty('customer').then(...);填写它。

我可能也很幸运。在首先搜索其父客户之后,我很有可能检索到的订单。这意味着客户已经在缓存中,我可以依靠微风自动将它们连接到相关的子订单。

如果我认为我的客户端应用程序会表现更好,我会考虑编写一个服务器端端点(OrdersWithCustomers),它将订单和相关客户组合在同一个负载中。这样的终点是:

  • 获取所要求的订单
  • 单独请求获取相关客户
  • 将客户填入每个订单的Order.Customer属性
  • 将此合成聚合物发送给客户。

Breeze将知道如何处理它...如果我给它正确的指导(更多关于另一次)。 Breeze可以在Order.Customer属性中提取客户数据,并自动将其放入缓存中。