Простое объяснение хранилища данных Google App Engine NDB
Я создаю приложение Google App Engine (python), и я узнаю об общей структуре. Я смотрел учебник и документацию для хранилища данных NDB, и у меня возникли трудности с обволакиванием концепций. У меня большой фон с базами данных SQL, и я никогда не работал с какой-либо другой системой хранения данных, поэтому я думаю, что там, где у меня возникают проблемы.
Мое настоящее понимание таково: хранилище данных NDB - это совокупность объектов (аналогичных записям БД), которые имеют свойства (аналогичные полям/столбцам БД). Объекты создаются с использованием модели (аналогичной схеме БД). Каждый объект имеет ключ, который генерируется для него, когда он хранится. Здесь я столкнулся с проблемой, потому что эти ключи, похоже, не имеют аналогии ни с чем в понятиях SQL DB. Они кажутся похожими на первичные ключи для таблиц, но они более тесно связаны с записями и фактически являются полями. Эти ключи NDB не являются свойствами объектов, но считаются отдельными объектами из объектов. Если объект хранится в хранилище данных, вы можете получить этот объект, используя его ключ.
Один из моих больших вопросов - где вы получаете ключи для этого? В некоторых документах, которые я видел, были показаны примеры, в которых ключи были просто созданы. Я этого не понимаю. Казалось, что когда объекты хранятся, метод put()
возвращает ключ, который может быть использован позже. Итак, как вы можете просто создавать ключи и определять идентификаторы, если исходные ключи генерируются хранилищем данных?
Еще одна вещь, с которой я, похоже, борюсь, - это концепция родословной с ключами. Вы можете определить родительские ключи любого типа, который вы хотите. Есть ли для этого предопределенная схема? Например, если у меня был подкласс класса под названием "Человек", и я создал ключ вида "Лицо", могу ли я использовать этот ключ в качестве родителя любого другого типа? Например, если бы я хотел, чтобы ключ "Чистка" был ребенком ключа "Человек", могу ли я затем объявить ключ "Автомобиль" дочерним по отношению к этому же "Человеческому" ключу? Или я не смогу после добавления ключа "Обувь"?
Мне бы просто понравилось простое объяснение хранилища данных NDB и его API для кого-то, исходящего из основного фона SQL.
Ответы
Ответ 1
Я думаю, что у вас слишком много неприятностей. Когда вы создаете сущность, вы можете либо дать ей именованный ключ, который вы выбрали сами, либо оставить это, и позволить хранилищу данных выбрать числовой идентификатор. В любом случае, когда вы вызываете put
, хранилище данных вернет ключ, который хранится в форме [<entity_kind>, <id_or_name>]
(на самом деле это также включает идентификатор приложения и любое пространство имен, но я оставлю это для ясности).
Вы можете сделать сущности членами группы сущностей, предоставив им предка. Этот предок на самом деле не должен ссылаться на существующий объект, хотя обычно это происходит. Все, что происходит с предком, состоит в том, что ключ объекта включает ключ предка: теперь он выглядит как [<parent_entity_kind>, <parent_id_or_name>, <entity_kind>, <id_or_name>]
. Теперь вы можете получить только объект, включив его родительский ключ. Итак, в вашем примере объект Shoe может быть дочерним по отношению к Человеку, независимо от того, было ли оно создано ранее: это ребенок, который знает о предке, а не наоборот.
(Обратите внимание, что путь родословной может быть продлен произвольно: дочерний объект сам может быть предком и т.д. В этом случае группа определяется сущностью в верхней части дерева.)
Сохранение объектов как части группы имеет преимущества с точки зрения согласованности, поскольку запрос внутри группы сущностей всегда гарантированно полностью согласован, тогда как вне запроса только в конечном итоге будет согласован. Однако есть и недостатки, поскольку скорость записи группы объектов ограничена 1 секундой для всей группы.
Ответ 2
Datastore ключи немного похожи на внутренние идентификаторы строк SQL, но, конечно, не совсем. Идентификаторы в Appengine немного похожи на первичные ключи SQL. Чтобы поддерживать децентрализованное одновременное создание новых ключей многими экземплярами приложений в облаке серверов, AppEngine внутренне генерирует ключи, чтобы гарантировать уникальность. Ваше приложение определяет параметры (идентификатор приложения, необязательное пространство имен, вид и необязательный идентификатор объекта), который AppEngine использует для засеивания его генератора ключей. Если вы не предоставите идентификатор, AppEngine будет сгенерировать уникальный числовой идентификатор, который вы можете прочитать.
Конечная согласованность требует времени, поэтому иногда более эффективно запрашивать несколько новых ключей навалом. Затем AppEngine генерирует для вас ряд идентификаторов числовых объектов. Вы можете читать свои значения из ключей как метаданные KeyProperty.
Ancestry используется для группировать вместе записи связанных объектов всех видов с целью transactions и isolation. Для этого нет предопределенной схемы, но вы ограничены одним родителем на каждого ребенка.
В вашем примере у одного конкретного Обуви может быть определенное Лицо как родитель. Другой конкретный ботинок может иметь лошадь в качестве родителя. И у другой обуви нет родителя. Многие субъекты всех видов могут иметь одного и того же родителя, поэтому несколько субъектов автомобилей могут также иметь это начальное лицо как родительское. Хранилище данных является схематичным, поэтому до вашего приложения разрешить или запретить автомобиль иметь лошадь в качестве родителя.
Обратите внимание, что дочерний элемент знает своего родителя, но родитель не знает его детей, потому что реализация будет влиять на масштабируемость.