ndb验证事务中的实体唯一性 [英] ndb verify entity uniqueness in transaction

查看:103
本文介绍了ndb验证事务中的实体唯一性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试创建一个属性,该属性应该是唯一的或无",类似于:

I've been trying to create entities with a property which should be unique or None something similar to:

class Thing(ndb.Model):
  something = ndb.StringProperty()
  unique_value = ndb.StringProperty()

由于ndb无法指定属性应该是唯一的,所以我自然会像这样手动进行操作是很自然的:

Since ndb has no way to specify that a property should be unique it is only natural that I do this manually like this:

def validate_unique(the_thing):
  if the_thing.unique_value and Thing.query(Thing.unique_value == the_thing.unique_value).get():
      raise NotUniqueException 

在我想在用于创建/更新实体的ndb事务中执行此操作之前,这就像一种魅力.喜欢:

This works like a charm until I want to do this in an ndb transaction which I use for creating/updating entities. Like:

@ndb.transactional
def create(the_thing):
  validate_unique(the_thing)
  the_thing.put() 

但是ndb似乎只允许祖先查询,问题是我的模型没有祖先/父代.我可以执行以下操作来防止出现此错误:

However ndb seems to only allow ancestor queries, the problem is my model does not have an ancestor/parent. I could do the following to prevent this error from popping up:

@ndb.non_transactional
def validate_unique(the_thing):
  ...

这感觉有点不合时宜,将某事物声明为事务,然后在事务外部进行一个(重要)部分的处理.我想知道这是否是可行的方法,或者是否有(更好的)替代方法.

This feels a bit out of place, declaring something to be a transaction and then having one (important) part being done outside of the transaction. I'd like to know if this is the way to go or if there is a (better) alternative.

关于ndb为什么只允许祖先查询的一些解释也很好.

Also some explanation as to why ndb only allows ancestor queries would be nice.

推荐答案

由于您的唯一性检查涉及一个(全局)查询,因此这意味着它受

Since your uniqueness check involves a (global) query it means it's subject to the datastore's eventual consistency, meaning it won't work as the query might not detect freshly created entities.

如果您的预期用法允许您使用这样的数据体系结构(或其他一些高度一致的方法),则一个选项是切换到祖先查询.

One option would be to switch to an ancestor query, if your expected usage allows you to use such data architecture, (or some other strongly consistent method) - more details in the same article.

另一种选择是使用一条额外的数据作为临时缓存,您将在其中存储所有新创建的实体的列表一会儿"(这使它们有足够的时间在全局查询中可见),除了查询结果中的值以外,您还需要检入validate_unique().这样一来,您就可以在事务外部进行查询,并且仅在唯一性仍然存在的情况下才进入事务,但最终结果是在事务内部手动检查缓存(即在事务内部没有查询).

Another option is to use an additional piece of data as a temporary cache, in which you'd store a list of all newly created entities for "a while" (giving them ample time to become visible in the global query) which you'd check in validate_unique() in addition to those from the query result. This would allow you to make the query outside the transaction and only enter the transaction if uniqueness is still possible, but the ultimate result is the manual check of the cache, inside the transaction (i.e. no query inside the transaction).

根据数据存储区对具有相同父级(或根本没有父级)的特定实体模型的唯一实体ID的实施,存在第三种选择(以价格的增加会消耗一些存储空间).您可以有一个这样的模型:

A 3rd option exists (with some extra storage consumption as the price), based on the datastore's enforcement of unique entity IDs for a certain entity model with the same parent (or no parent at all). You could have a model like this:

class Unique(ndb.Model):  # will use the unique values as specified entity IDs!
    something = ndb.BooleanProperty(default=False)

您将以这种方式使用(示例使用唯一"父键,该键可将模型重新用于具有唯一值的多个属性,如果不需要,可以将其完全删除):

which you'd use like this (the example uses a Unique parent key, which allows re-using the model for multiple properties with unique values, you can drop the parent altogether if you don't need it):

@ndb.transactional
def create(the_thing):
    if the_thing.unique_value:
        parent_key = get_unique_parent_key()
        exists = Unique.get_by_id(the_thing.unique_value, parent=parent_key)
        if exists:
            raise NotUniqueException
        Unique(id=the_thing.unique_value, parent=parent_key).put()
    the_thing.put()


def get_unique_parent_key():

    parent_id = 'the_thing_unique_value'
    parent_key = memcache.get(parent_id)
    if not parent_key:
        parent = Unique.get_by_id(parent_id)
        if not parent:
            parent = Unique(id=parent_id)
            parent.put()
        parent_key = parent.key
        memcache.set(parent_id, parent_key)
    return parent_key

这篇关于ndb验证事务中的实体唯一性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆