Скаляры SQLAlchemy и аномалия пересеченияPython

Программы на Python
Anonymous
Скаляры SQLAlchemy и аномалия пересечения

Сообщение Anonymous »

В руководстве SQLAlchemy указано*, что метод Session.scalars() возвращает объекты ORM.
*Выбор записей ORM
В следующем коде показаны два примера, один из которых возвращает объект ORM, а другой — нет. Первый использует оператор выбора, который выбирает один объект ORM. Второй пример не возвращает объект ORM. Он идентичен, за исключением введения функции intersect() SQLAlchemy. Он возвращает только первый столбец нужного объекта.
Хотя можно выбрать первичные ключи записей, а затем выполнить второй выбор для объектов ORM, что выглядит как кладж. Есть ли более элегантное решение?
from sqlalchemy import create_engine, select, intersect
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session

class Base(DeclarativeBase):
pass

class Movie(Base):
__tablename__ = "movie"

title: Mapped[str]
id: Mapped[int] = mapped_column(primary_key=True)

def __repr__(self):
return (
f"{self.__class__.__qualname__}("
f"title={self.title!r}, "
f"id={self.id!r})"
)

engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(engine)
with Session(engine) as session:
movie_1 = Movie(title="Great Movie 1")
movie_2 = Movie(title="Great Movie 2")
session.add_all((movie_1, movie_2))

statement = select(Movie).where(Movie.title == "Great Movie 1")
print("\n", statement)
result = session.scalars(statement).all()
print(f"{result=}")

stmt_isec = intersect(statement)
# In case you're wondering, the next line has the same effect as
# the unary intersect.
# stmt_isec = intersect(*[statement, statement])
print("\n", stmt_isec)
result = session.scalars(stmt_isec).all()
print(f"{result=}")

Выход:
SELECT movie.title, movie.id
FROM movie
WHERE movie.title = :title_1
result=[Movie(title='Great Movie 1', id=1)]

SELECT movie.title, movie.id
FROM movie
WHERE movie.title = :title_1 INTERSECT SELECT movie.title, movie.id
FROM movie
WHERE movie.title = :title_1
result=['Great Movie 1']

Сценарий использования
Ценность функции пересечения SQLAlchemy заключается в ее поддержке оператора сопоставления Python. Я проиллюстрировал это в примере «Наивный фильм_мешок» ниже. Однако это только половина истории. Оператор match обеспечивает мощные функции поиска, поддерживаемые универсальными пакетами данных. Инкапсуляция данных в пакеты упрощает разработку программ и макеты графического интерфейса. Это показано в следующем разделе «Изысканный фильм_мешок».
# Naïve movie_bag
movie_bag = {
"year": 1943,
"star": "Humphrey Bogart",
}
statements = []
for column, criteria in movie_bag.items():
match column:
case "year":
statements.append(select(Movie).where(Movie.year == criteria))
case "director":
statements.append(select(Movie).where(Movie.director == criteria))
case "star":
statements.append(select(Movie).where(Movie.star == criteria))
intersect(*statements)

# Sophisticated movie_bag
movie_bag = {
"year": "1939-1945",
"stars": ["Humphrey", "Bergman"],
}
statements = []
for column, criteria in movie_bag.items():
match column:
case "year":
statements.append(
select(Movie).where(Movie.yearMovie.year.in_(list(criteria)))
)
case "director":
for director in criteria:
statements.append(
(
select(Movie)
.select_from(Movie)
.join(Movie.directors)
.where(Person.name.like(f"%{director}%"))
)
)
case "star":
for star in criteria:
statements.append(
(
select(Movie)
.select_from(Movie)
.join(Movie.stars)
.where(Person.name.like(f"%{star}%"))
)
)
intersect(*statements)


Подробнее здесь: https://stackoverflow.com/questions/787 ... ct-anomaly

Вернуться в «Python»