2012-04-24 3 views
0

Я моделирую данные, идентификаторы которых должны быть с автоматическим приращением. На самом деле, я создал рабочую модель, но мне нужно дать совет от гуру хранилища данных.App Engine datastore: ID auto increment with NDB

Существует мой код для генерации ID:

class AutoIncrementModel(ndb.Model): 
    entity_id = ndb.IntegerProperty('eID') 
    def _pre_put_hook(self): 
    if self.key and self.key.id(): return 
    latest = self.__class__.query().order(-self.__class__.entity_id).get() 
    self.entity_id = latest and latest.entity_id + 1 or 1 
    while self.__class__.get_by_id(self.entity_id): self.entity_id += 1 
    self.key = ndb.Key(self.__class__.__name__, self.entity_id, parent=self.key and self.key.parent() or None) 
    self.put() 

Этот код генерирует простые идентификаторы, но я совсем не уверен, что это достаточно хорошо.

UPD: Этот код не работает. Несколько объектов могут быть записаны с одним ключом, и данные могут быть перезаписаны.

№1. Может ли это вызвать проблему потери данных? «While loop» сохраняет приложение от генерации идентификатора. Но я не уверен, что нет возможности перезаписи данных.

№2. Может ли такая транзакция лучше экономить?

def _pre_put_hook(self): 
    def callback(): 
     while self.__class__.get_by_id(self.entity_id): self.entity_id += 1 
     self.key = ndb.Key(self.__class__.__name__, self.entity_id, parent=self.key and self.key.parent() or None) 
     self.put() 
    if self.key and self.key.id(): return 
    latest = self.__class__.query().order(-self.__class__.entity_id).get() 
    self.entity_id = latest and latest.entity_id + 1 or 1 
    ndb.transaction(callback, xg=True) 

UPD: Сделка помогает избежать потери данных. Этот код работает намного лучше, чем первый пример.

№3. Есть ли способ получить максимальный ID из группы объектов без дополнительного поля для индекса?

+2

Трудно избежать состояния гонки при создании последовательных идентификаторов в распределенной системе, и я не думаю, что ваш первый пример преуспевает в этом. По крайней мере, вам потребуется задействовать транзакцию (хотя я не уверен, работает ли ваш второй пример.) (Также см. Http://stackoverflow.com/questions/3985812/how-to-implement- autoincrement-on-google-appengine, хотя возможно, что ndb меняет вещи, поэтому я не проголосовал за закрытие как дубликат). – geoffspear

+1

Почему вы (думаете, что вам) нужны последовательные идентификаторы? Хранилище данных имеет вполне удовлетворительный способ генерации _unique_ ID. –

ответ

2

В принципе, этого не может быть сделано. Вам нужен внешний счетчик «singleton» и должен добавить общий доступ к производительности, если вам нужно больше, чем примерно одна запись в секунду. См. How to implement "autoincrement" on Google AppEngine для обсуждения вариантов.

0

не имеет смысла называть «я». класс .entity_id »поле beacuse это поле является уникальным идентификатором, никогда не имеет инкрементного значения, нет смысла добавлять ни того, ни другого.