2013-11-07 4 views
2

я должен добавить одно новое свойство в существующий класс НБД:Как присвоить значение по умолчанию всем записям хранилища NDB?

class AppList(ndb.Model): 
    ... 
    ignore = ndb.BooleanProperty(default=False) # new property 

Тогда я буду использовать его, как показано ниже:

entries = AppList.query() 
entries = entries.filter(AppList.counter > 5) 
entries = entries.filter(AppList.ignore == False) 
entries = entries.fetch() 

Я не могу использовать AppList.ignore != True поймать рано добавил записи (которые дон 't имеет свойство ignore), поэтому я должен назначить False для всех записей в моем объекте AppList. Каков наиболее эффективный способ сделать это? В настоящее время этот объект содержит около 4 000 записей.

Обновление. Я решил использовать следующий уродливый код (не удалось применить cursors), он работает как задание cron. Но разве я не обновляю все 100 записей каждый раз?

entities = AppList.query() 
# entities = entities.filter(AppList.ignore != False) 
entities = entities.fetch(100) 
while entities: 
    for entity in entities: 
     entity.ignore = False 
     entity.put() 
    entities = AppList.query() 
    # entities = entities.filter(AppList.ignore != False) 
    entities = entities.fetch(100) 

ответ

2

не стоит забывать, что есть библиотека MapReduce, которая используется в этих случаях. Но я считаю, что лучший способ - использовать все эти предложения.

Теперь вам нужно получить() и поставить() 4000 объектов, и вопрос заключается в том, как уменьшить «затраты» на эту операцию.

Мне просто интересно узнать, что возвращает ваш bool(entity.ignore). Если свойство missing возвращает False, вы можете настроить код, считая его False, и отложить операцию.Если вы поместите() по другой причине, свойство ignore написано на False благодаря аргументу по умолчанию. Таким образом, для остальных объектов можно запустить такой скрипт (через remote_api):

def iter_entities(cursor=None): 
    entries = AppList.query() 
    res, cur, more = entries.fetch_page(100, start_cursor=cursor) 
    put_queue = [ent for ent in res if not hasattr(ent, 'ignore')] 
    # put_queue = [] 
    # for ent in res: 
    # if not hasattr(ent, 'ignore'): 
    #  put_queue.append(ent) 
    ndb.put_multi(put_queue) 
    if more: 
     iter_entities(cur) # a taskqueue is better 
+0

Спасибо. Не могли бы вы прояснить, что делает следующая строка: 'put_queue = [ent for ent in res if not hasattr (ent, 'ignore')]'? Если в записи нет атрибута «игнорировать», то что? –

+0

Ответ отредактирован: ndb.get_multi() нуждается в списке сущностей. строка создает список с внутри только объектов, которые не имеют свойства «игнорировать». он делает то же самое из 4 новых строк. –

+0

Хм. Правильно ли я это понимаю - ваш код на самом деле не присваивает значение по умолчанию 'False' для свойства' ignore'? То есть в одной строке отсутствует 'ent.ignore = False' перед' put_queue.append (ent) '? –

2

Вы можете попробовать использовать hasattr, чтобы проверить, не имеет ли запись свойство ignore.

Если вы просто хотите назначить False для всех записей в объекте AppList, вам просто нужно сделать обновление к вашей схеме (перезагрузить файл models.py), а затем вы должны установить свойство False.

Более подробную информацию о обновлении схемы можно найти here.

EDIT: ответить на Ваш комментарий:

if hasattr(entity, 'ignore'): 
    #your code goes here 
+0

Как использовать 'hasattr' с' fetch'? См. Мой обновленный вопрос - главный вопрос - как получить объекты без этого атрибута. –

1

Самый простой способ без развертывания нового кода, будет использовать удаленный API и выполнять запрос, получающий все сущности и устанавливающий значение свойства false, а затем put(). 4000 записей не много.

На самом деле вам даже не нужно явно указывать значение, оно будет установлено при получении значения по умолчанию, если оно не имеет значения в настоящее время.

+0

К сожалению, похоже, что мне нужно установить значение - см. Мой вопрос, если я использую 'query', то он не« применяет »значение по умолчанию. –

+0

О, хорошо, это просто для цикла по результирующему набору, задайте значение и поместите. –

2

Ваш обновленный код обновит только первые 100 объектов. попробуйте использовать курсор

https://developers.google.com/appengine/docs/python/ndb/queries#cursors

если и не могу использовать курсор, а затем использовать смещение и продолжать увеличивать смещение по 100 на каждом цикле или извлечь все записи один раз выборки() (курсор подход лучше один)

и вместо того, чтобы их один за одним использованием ndb.put_multi (список лиц, положить)

это будет более быстрее, чем положить один на один

+0

Спасибо. Я пытался использовать 'курсоры', но я не понимаю, что должно быть значением' start_cursor', когда я называю это вторым/третьим и т. Д. Времени. –

+0

Каждый раз, когда вы делаете запрос с помощью курсора, вы получите набор данных и курсор, пока не достигнете конца данных, и у вас нет курсора (или курсор - «Нет», я забываю, что). – deweyredman

Смежные вопросы