Редактирование App Engine экземпляра в повторяющемся KeyProperty через сам экземпляр

Допустим, у меня есть следующие модели:

class Author(ndb.Model)
    books = ndb.KeyProperty(kind='Book', repeated=True)

class Book(ndb.Model)
    title = ndb.StringProperty()

Итак, в определенный момент у вас будет автор со списком из n книг.

Вопросы: когда я редактирую книгу, как изменить автора без ссылки на «текущего» автора? Нужно ли добавлять обратную связь с KeyProperty на Book?

При смене автора я должен удалить книгу из списка старых авторов и добавить ее в новый. Это кажется обременительным. Есть ли способ лучше?

Дополнительный вопрос: что делать, если книга будет удалена? В списке книг автора будет значение None. Должен ли я удалить это?

Примечание. Я использую повторяющееся свойство KeyProperty, потому что это упрощает заказ книг, что в моем случае важно.


person Sander van Leeuwen    schedule 25.11.2015    source источник


Ответы (2)


Когда я редактирую книгу, как мне изменить автора без ссылки на «текущего» автора?

вы можете использовать ndb.Model.allocate_ids для резервирования ключа перед сохранением сущности

Нужно ли добавлять обратную связь с KeyProperty в книге?

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

Что делать, если книгу удалили? В списке книг автора будет значение None. Должен ли я удалить это?

В этом случае ключ в Auther.books не станет автоматически нулевым. Вы должны удалить его самостоятельно.

Я использую повторяющееся свойство KeyProperty, потому что это упрощает заказ книг, что в моем случае важно.

Потенциальная проблема заключается в том, что размер объекта ограничен 1 МБ. Если автор очень плодовитый писатель (например, у Эдви Сирлза Брукса более 800 опубликованных работ), лимит может быть превышен.

Я бы спроектировал модель так:

class Author(ndb.Model):
    name = ndb.StringProperty()

class Book(ndb.Model):
    authors = ndb.KeyProperty('Author', required=True)  # Usually it is at most a couple of authors  
    title = ndb.StringProperty()

Чтобы узнать все книги, написанные конкретным автором с id 1234, вы можете

  Book.query(Book.authors == ndb.Key('Author', 1234)).fetch()

По-видимому, порядок книг должен храниться явно, я бы предложил третью сущность для отслеживания этой информации:

class BookList(ndb.Model):
  name = ndb.StringProperty()
  book_keys = ndb.KeyProperty(kind='Book', repeated=True)

Затем вы можете получить книги таким образом

stephen_king_book_list = stephen_king_book_list_key.get()
books = ndb.get_multi(stephen_king_book_list.book_keys)
# Some of key can lead to None if the underlying book is already deleted
# You can define some background job to sweep clean the list from time to time 
# But let filter out the bad guys first 
books = [b for b in books if b]  

Если вы думаете, что ваши списки будут очень-очень длинными, вы можете разбить список на сегменты, например структуру связанного списка.

class BookList(ndb.Model):
  prev_segment = ndb.KeyProperty(kind='BookList', required=False)
  next_segment = ndb.KeyProperty(kind='BookList', required=False)
  name = ndb.StringProperty()
  book_keys = ndb.KeyProperty(kind='Book', repeated=True)

Вы можете легко найти первый сегмент:

  starting_point = BookList.query(BookList.name == 'Stephen_King',
     BookList.prev_segment == None
  ).fetch()

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

person Anthony Kong    schedule 25.11.2015
comment
Спасибо за Ваш ответ. Возможно, мой пример книги/автора не самый лучший для моего варианта использования. Как уже говорилось, порядок очень важен. Думайте об этом как об отношении Презентация/Слайд. Я также предпочитаю ваше предложение по дизайну, но как бы вы позаботились о порядке слайдов в презентации? Или книги в списке авторов книг. - person Sander van Leeuwen; 25.11.2015
comment
Используйте order by cloud.google.com/appengine/docs/ python/datastore/ Используя пример book, вы можете отсортировать результат по некоторым критериям, таким как publication_date - person Anthony Kong; 25.11.2015
comment
Порядок должен быть управляемым: книга должна иметь возможность перемещаться вверх и вниз по авторскому списку книг. Этого можно добиться с помощью свойства sort_value. Но когда вы хотите переместить книгу (путем изменения sort_value), вам нужно обновить sort_value для всех книг автора, что потребует запроса для каждой книги, верно? - person Sander van Leeuwen; 25.11.2015
comment
Я бы предложил какую-то конструкцию, похожую на music playlist, чтобы отслеживать порядок. Вам просто нужно помнить о лимите объекта в 1 МБ. Я обновлю ответ, чтобы отразить это - person Anthony Kong; 26.11.2015

Ваши отношения действительно неправильные. У вас должно быть одно свойство KeyProperty в книге, указывающее на автора; затем, если вы хотите запросить все книги одного автора, вы можете запросить ключ автора.

person Daniel Roseman    schedule 25.11.2015
comment
Спасибо за Ваш ответ. Можете ли вы проверить комментарии под ответом Энтони? Порядок очень важен, поэтому я смоделировал его таким образом. Таким образом, я могу воспользоваться порядком в свойстве повторяющегося ключа, которое представляет собой список. - person Sander van Leeuwen; 25.11.2015