StructuredProperty是否引用父级或子级?

2024-04-27 14:54:28 发布

您现在位置:Python中文网/ 问答频道 /正文

StructuredProperty是否引用父级或子级?在

class Invoices(ndb.Model): #Child

class Customers(ndb.Model): #Parent
    invoice = ndb.StructuredProperty(Invoices)

或者。。。在

^{pr2}$

Tags: childmodelinvoiceclassparentinvoicesndbcustomers
1条回答
网友
1楼 · 发布于 2024-04-27 14:54:28

在“NoSQL数据存储的最佳实践是什么”的上下文中回答您的问题, 这是我能提供的。在

首先,你可能想用单数来命名你的模型,因为它们应该描述单个的 Invoice或{}实体,不是多个。在

接下来,使用StructuredProperty表示您希望将所有这些信息保存在 单一实体-这将减少写/读操作,但可能会引入一些限制。 (见docs- 或者这个related question

最常见的关系是一对多(Customer)对多(Invoice)关系, 其结构如下:

class Invoice(ndb.Model): #Child
    invoice_id = ndb.StringProperty(required=True)  # 

class Customer(ndb.Model): #Parent
    invoices = ndb.StructuredProperty(Invoices, repeated=True)

    def get_invoice_by_id(self, invoice_id):
        """Returns a customer Invoice by invoice_id. Raises KeyError if invoice is not present."""
        invoice_matches = [iv for iv in self.invoices if iv.invoice_id == invoice_id]
        if not invoice_matches: raise KeyError("Customer has no Invoice with ID %s" % invoice_id)
        return invoice_matches[0]  # this could be changed to return all matches

请记住此实施的以下限制:

  1. StructuredPropertys不能在其内部包含重复的属性。在
  2. 保持invoice_id全局唯一性的复杂性将比Invoice在自己的实体组中更高。(invoice_key.get()总是比这需要的查询更好)
  3. 您需要Customer上的一个实例方法来通过invoice_id找到{}。在
  4. 您需要逻辑来防止在单个Customer上存在具有相同ID的发票

以下是一些优点:

  1. 您可以查询Customer
  2. 通过invoice_id查询Invoice将返回Customer实例以及所有发票。(事实上,这可能是有利的也可能是不利的——你需要逻辑来从客户那里退回发票)

这里有一个比较常见的解决办法,但决不一定是“正确的解决办法” 此解决方案使用祖先关系,允许您保持对Invoice和 相关的Customer原子-因此您可以在 Customer级别。(total_orderstotal_gross等)

^{pr2}$

祝阿彭金好运!一旦你掌握了所有这些的窍门,它将是一个真正有价值的平台。在

更新:

这里有一些额外的代码,用于事务性地更新我上面提到的客户合计总数。在

def create_invoice(customer_key, gross_amount_paid):
    """Creates an invoice for a given customer.

    Args:
        customer_key: (ndb.Key) Customer key
        gross_amount_paid: (int) Gross amount paid by customer
    """

    @ndb.transactional
    def _txn():
        customer = customer_key.get()
        invoice = Invoice(parent=customer.key, gross_amount=gross_amount_paid)

        # Keep an atomic, transactional count of customer aggregates
        customer.total_gross += gross_amount_paid
        customer.total_orders += 1

        # batched put for API optimization
        ndb.put_multi([customer, invoice])  

        return invoice

    return _txn()

上面的代码在single entity group transaction(例如ndb.transactional(xg=False))中工作,因为Invoice是{}的子实体。如果该连接丢失,则需要xg=True。(我不确定它是否更贵,但优化程度较低)

相关问题 更多 >