NDB的put()有多可靠?

时间:2013-10-15 04:51:26

标签: google-app-engine app-engine-ndb

我的模特有一些奇怪的行为。

我有事件模型,可以记录事件。还有一个“聚合”模型,它存储模型A的记录集合,按日期分组。

class Event(ndb.Model):
    user = ndb.KeyProperty(kind=UserProfile)
    date = ndb.DateTimeProperty(auto_now_add=True)
    event_type = ndb.StringProperty()
    is_aggregated = ndb.BooleanProperty(default=False)

class Aggregate(ndb.Model):
    user = ndb.KeyProperty(kind=UserProfile)
    date = ndb.DateProperty()
    aggregates = ndb.PickleProperty(default={})

Event 有一个aggregate()方法,如下所示:

def aggregate(self):
    if self.is_aggregated:
        # already aggregated
        return

    # get an existing aggregate
    agg = Aggregate.query(
        Aggregate.user == self.user,
        Aggregate.date == self.date.date()
    ).get()
    if not agg:
        # or create a new one
        agg = Aggregate(
            user=self.user,
            date=self.date.date()
        )
        agg.put()

    # update aggregate's count
    if self.event_type not in agg.aggregates.keys():
        agg.aggregates[self.event_type] = 0
    agg.aggregates[self.event_type] += 1
    agg.put()

    # mark this as aggregated
    self.is_aggregated = True
    self.put()

现在,在我的处理程序中,每次创建新的Event时,我都会调用其aggregate方法。 但这些数字存在一些差异。

例如,我有Eventdate2013-10-10 00:00:002013-10-10 23:59:59之间的event_type = "add"个记录,所有记录都is_aggregated = True 。这意味着aggregate方法为每个方法成功执行。

但是当我使用Aggregate查看相应的date = 2013-10-10记录时,aggregates属性不会反映20 "add"个事件。它只有16个。

会导致这种差异的原因是什么? self.put()如何成功但agg.put()不成功?

1 个答案:

答案 0 :(得分:3)

我认为您已经面临eventual consistency功能。每次您查询聚合模型时,都可以从不同的数据中心检索它们,这些数据中心可能包含稍微不同的聚合版本。特别是如果您的事件模型创建得足够快。

我会这样做:根据用户和日期手动编写聚合模型的字符串ID,然后通过此ID通过Aggregate.get_by_id()获取它(我认为用户有id):

# get an existing aggregate
agg_id = str(user.id) + '@' + self.date.date().strftime("%m/%d/%Y")
agg = Aggregate.get_by_id(agg_id)
if not agg:
    # or create a new one
    agg = Aggregate(key=ndb.Key(Aggregate, agg_id),
                    user=self.user,
                    date=self.date.date()
    )
    #agg.put() #ALSO, this put is not needed because you has one below