6

让我举一个简单的例子:你有一个订单和一个购物车。我设想持久化的一种方法是保存一个 Order 文档和一个 Cart 文档。Order 文档可能有一个名为“shopping-cart”的字段,其值是相关购物车文档的 UUID。我可以想象的另一种方法是保存一个带有“购物车”字段的订单文档,该字段包含整个购物车的关联数组。换句话说,我没有将购物车显式保存为独立文档,而是将购物车文档嵌入到订单文档中。

如果我们稍后决定 Cart 应该是持久的,那么返回的用户会发现他的半成品 Cart 正在跨会话等待他呢?我想我们可以结合这两种方法,在购物车不完整时将其分开,并在完成/购买时将其嵌入到订单文档中。

两种方法都可以,尽管我担心 CouchDB 没有外键约束;在第一种方法中,可以删除购物车文档,从而为您留下损坏的数据集。

您如何决定使用哪种方法?这些方法中的一种对 CouchDB 来说更惯用吗?有没有我错过的方法?

我是 CouchDB 的新手,所以我很难看出拥有或多或少标准化结构的优点/缺点。

4

2 回答 2

4

另一方面,如果它们不是一对一的,那么使用复杂的键,您可以使用视图排序规则进行连接。

function(doc) {
  if (doc.type == 'order') {
    emit([doc.cartid, 1], doc);
  } else if (doc.type == 'cart') {
    emit([doc.id, 0], doc);
  }
}

文档将由cartid 与购物车之后的订单进行整理。您的应用程序代码可以轻松加入此流,并且您可以使用 startkey 和 endkey 按特定 carid 进行查询。

请参阅:查看排序规则以了解排序规则。

您也可以使用 reduce 将它们连接在一起。

只需将地图功能更改为:

function(doc) {
  if (doc.type == 'order') {
    emit([doc.cartid, 1], {cartid: doc.cartid, orders: [doc]});
  } else if (doc.type == 'cart') {
    emit([doc.id, 0], {cartid: doc.id, orders: [], cart: doc);
  }
}

并添加一个这样的reduce函数:

function(keys, values) {
  var out = {cartid: null, orders: [], cart: null};
  for (idx in values) {
    var doc = values[idx];
    out['cartid'] = doc.cartid;
    if (doc.cart) { out['cart'] = doc.cart };
    for (idx2 in doc.orders) {
      out.orders.push(doc.orders[idx2]);
    }
  }
  return out;
}

这将为每个购物车返回一个文档,该文档将是一个购物车、一组订单文档和一个购物车文档。

如果上述代码中存在错误,我们深表歉意,但我没有方便的 couchdb 测试实例来试用它们。不过,您应该了解总体思路,CouchDB wiki 有更多详细信息。

于 2009-11-05T02:50:10.193 回答
0

如果 Order 和 Cart 对象具有一对一的关系(听起来就是这样),那么第二种方法最有意义……只需将关联的对象包含在一个中即可。这为您提供了您正在寻找的数据完整性并使其变得简单;-)

于 2009-11-04T14:33:10.270 回答