SQLAlchemy получает элементы из карты идентичности не только по первичному ключу

Можно ли использовать пару полей не из первичного ключа для извлечения элементов (уже выбранных ранее) из карты идентификации? Например, я часто запрашиваю таблицу (external_id, platform_id) пара, которая является уникальным ключом, но не первичным ключом. И я хочу опустить ненужные запросы SQL в таких случаях.

2 ответа

Краткий обзор identity_map и get():

Карта идентификаторов сохраняется для жизненного цикла SQLAlchemy session объект, т.е. в случае веб-службы или RESTful API session Жизненный цикл объекта не более одного request (рекомендуемые).

От: http://martinfowler.com/eaaCatalog/identityMap.html

Карта идентификации хранит записи обо всех объектах, которые были считаны из базы данных в одной бизнес-транзакции. Всякий раз, когда вам нужен объект, вы сначала проверяете карту идентичности, чтобы увидеть, есть ли у вас ее.

В ORM SQLAlchemy есть этот специальный метод запроса get() сначала смотрит в identity_map используя pk (только допустимый аргумент) и возвращает объект из карты идентичности, фактически выполняя SQL запрос и попадание в базу данных.

Из документов:

get(ident)

Вернуть экземпляр на основе заданного идентификатора первичного ключа или None если не найден

get() отличается тем, что обеспечивает прямой доступ к идентификационной карте владельца Session, Если указанный идентификатор первичного ключа присутствует в локальной карте идентификаторов, объект возвращается непосредственно из этой коллекции, и SQL не выдается, если только объект не был отмечен как полностью истекший. Если нет, выполняется SELECT для определения местоположения объекта.


Только get() использует identity_map - официальные документы:

Он в некоторой степени используется в качестве кэша, поскольку он реализует identity map шаблон и хранит объекты, привязанные к их primary key, Однако он не выполняет никакого кеширования запросов. Это значит, если вы говорите session.query(Foo).filter_by(name='bar'), даже если Foo(name='bar') прямо там, на карте идентичности, сессия не имеет представления об этом. Он должен выдать SQL в базу данных, вернуть строки обратно, а затем, когда он увидит первичный ключ в строке, он может просмотреть локальную карту идентификации и увидеть, что объект уже существует. Это только когда ты говоришь query.get({some primary key}) что сеанс не должен выдавать запрос.


PS Если вы запрашиваете, не используя pk ты не ударяешь identity_map на первом месте.


Несколько актуальных вопросов SO, полезно прояснить концепцию:

Принудительное использование sqlalchemy ORM get() вне карты идентификации

Можно получить доступ ко всей карте идентичности последовательно:

for obj in session.identity_map.values():
    print(obj)

Чтобы получить объект по произвольным атрибутам, вам нужно сначала отфильтровать тип объекта, а затем проверить ваши атрибуты.

Это не поиск в постоянное время, но может предотвратить ненужные запросы.

Существует аргумент, что объекты могли быть изменены другим процессом, и карта идентификации не содержит текущего состояния, но этот аргумент недействителен: если уровень изоляции транзакции равен read committed (или меньше) - и это часто бывает, данные ВСЕГДА могли быть изменены сразу после завершения запроса.

Другие вопросы по тегам