REST:创建具有交叉引用属性的项

时间:2015-09-01 06:12:01

标签: rest

我目前正在为我的应用中使用的资源设计架构(简化为' order' 此处)。我对交叉引用/能够引用一个还没有具体标识符的资源感到有些不满。

我下面有3个可能的设计。有些更接近对象的域+心理模型(A + C),B可能更简单,但涉及重定向映射(用于发送到服务器)以解决问题。

我的问题:在下面的3个设计中,哪个看起来最强健/正确? (或者,提供改进的解决方案)

详情:

我想要在一个请求中发送的资源是:

  
      
  • 订单      
        
    • 产品[]
    •   
    • 费用[]
    •   
    • 客户[]
    •   
  •   

一些上下文/我的约束是:

  • 每个产品&费用已分配给客户
  • '客户' property只是文本的快照 - 必须附加到一个订单。 (它不打算成为一组可重复使用的客户)
  • 在域中,大多数UI /分析都围绕整个订单的总计。
    • 仅在少数情况下,我们会查看“每个客户”的数据。图
  • 同一对象有时用于瞬态查询
    • 例如:计算运费。 (因此,对于此资源架构,数据库持久性并不总是给定的)

选项A:首先创建客户,然后使用他们的ID

如果客户是依赖关系,那么我可以事先创建它们。通过输入检查,我可以保持每个客户'仅与1个订单相关联。

此选项表示不能在一个请求中完成所有操作。

注意:它还假定客户必须坚持使用数据库。例如,我无法通过瞬态运行同一个对象来计算运费'查询。

POST: {
    name: "Person 1",
}
-> ID: 81

POST: {
    name: "Person 2",
}
-> ID: 92

{
    products: [{
        productId: 3,
        quantity: 2,
        customer: 81
    }, {
        productId: 4,
        quantity: 1,
        customer: 92
    }],
    fees: [{
        feeId: 21,
        amount: 30,
        customer: 81
    }, {
        feeID: 32,
        amount: 2,
        customer: 92
    }]
}

选项B:围绕客户重新定位数据包

看起来很干净 - 虽然它会涉及到这种格式的UI映射,但数据库可能会映射回使用类似选项A / C 的格式。

{
    customerOrders: [{
        name: "Person 1",
        products: [{
            productId: 3,
            quantity: 2
        }],
        fees: [{
            feeId: 21,
            amount: 30
        }]
    }, {
        name: "Person 2",
        products: [{
            productId: 4,
            quantity: 1
        }],
        fees: [{
            feeID: 32,
            amount: 2
        }]
    }]
}

选项C:交叉引用属性和临时ID

这与选项A类似,只是探索是否可以在一个请求中完成所有操作。生成临时ID +使服务器处理它似乎很尴尬 - 但我认为实际上可能有一种优雅的方式来实现它。

{
    products: [{
        productId: 3,
        quantity: 2,
        customer: "a"
    }, {
        productId: 4,
        quantity: 1,
        customer: "b"
    }],
    fees: [{
        feeId: 21,
        amount: 30,
        customer: "a"
    }, {
        feeID: 32,
        amount: 2,
        customer: "b"
    }],
    customers: [{
        name: "Person 1",
        tempId: "a"
    }, {
        name: "Person 2",
        tempId: "b"
    }]    
}

2 个答案:

答案 0 :(得分:1)

because you want to use single call, all the references customer-product-fee are relative. Something like ID/IDREF in XML (see http://docstore.mik.ua/orelly/xml/schema/ch09_03.htm). All you need to do is check the references are valid.

In my opinion option A is out of question (you wanted single request, right?); B and C differs only in the semantic: a person belongs to product/fee or product/fee belongs to a person. B seems to be the easiest to implement.

答案 1 :(得分:1)

首先要关注的是了解资源的功能范围。例如,使用订单创建客户可能不具有凝聚力。 /订单资源应按订单运行。

第二个问题是了解您正在POST / PUT / GET / DELETE-ing的资源的性质。它是一个实例;它是一个集合?使用POST / PUT时,要考虑的约定是将资源视为实例(在本例中为“order”)。

第三个问题是确定任何包含的对象是否也是资源。 “产品”肯定似乎是候选人。

最后,将资源视为具有URL的ID;因此可以在其他资源中被称为超媒体。使用类似HAL的方法是一种引用外部资源的机制。

所以你的1-call限制可能是一个挑战。实际上,单个呼叫可能会影响可重用性。所以选项1最接近答案。

例如,订单资源可能包含集合产品自定义(1个由特定客户定制的通用产品)。这些链接提供了对产品,客户和自我的参考。

{
  "product_customisations" : [{
    "id" : "001",
    "qty" : 2,
    "fees" : {
      "type" : "fee_1",
      "amount" : {
        "amt" : "10.00",
        "currency" : "NZD"
      }
    }
    "_links" : {
      "self" : {"href" : "/products_customisations/001"},
      "product" : {""href" : "/products/001"},
      "customer" : {"href" : "/products/001"}
    }
  }]
}