Получить строки из связанной таблицы (объект ORM) через array_agg()

Я хочу получить массив данных таблицы продуктов, используя функцию array_agg. В Postgers это прекрасно работает, но в SQLalchemy это можно сделать только с такими типами данных, как целые числа, строки и т. д. Как мне реализовать это в SQLalchemy?

Код в postgresql:

   select DISTINCT
        seller.title, array_agg(product), COUNT(product.id)
        from seller_product
            INNER JOIN seller ON seller.ozon_id = seller_product.id_seller 
            INNER JOIN product ON product.ozon_id = seller_product.id_product 
        WHERE start_id = 36
        GROUP BY seller.title ORDER BY COUNT(product.id) DESC

Код на питоне. Я пытаюсь сделать это так:

slct_stmt_now = select(Seller, func.array_agg(Product.__table__), func.count(Product.id)).distinct().select_from(seller_product)
    slct_stmt_now = slct_stmt_now.join(Seller, Seller.ozon_id == seller_product.columns["id_seller"]).join(Product, Product.ozon_id == seller_product.columns["id_product"]).where(seller_product.columns["start_id"] == LAST_START_ID).group_by(Seller)
now_data_txt = session.execute(slct_stmt_now.order_by(func.count(Product.id).desc())).all()

Я не думаю, что SQLAlchemy в настоящее время поддерживает это, см. github.com/sqlalchemy/sqlalchemy/discussions/11156

snakecharmerb 27.06.2024 14:48

Да. Это работает. Спасибо!

Andrey 27.06.2024 15:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обсуждение на GitHub, которое @snakecharmerb цитирует выше, включает комментарий

отношения делают именно то, что вы ищете, объектно-ориентированным способом.

# https://stackoverflow.com/q/78676983/2144390
# fmt: off
from sqlalchemy import Column, ForeignKey, Integer, String, Table, create_engine, select
from sqlalchemy.orm import Session, declarative_base, joinedload, relationship
# fmt: on

engine = create_engine("postgresql://scott:[email protected]/test")
Base = declarative_base()


seller_product = Table(
    "seller_product",
    Base.metadata,
    Column(
        "id_seller", Integer, ForeignKey("seller.ozon_id"), primary_key=True
    ),
    Column(
        "id_product", Integer, ForeignKey("product.ozon_id"), primary_key=True
    ),
)


class Product(Base):
    __tablename__ = "product"
    id = Column(Integer, primary_key=True)
    ozon_id = Column(Integer, nullable=False)
    name = Column(String, nullable=True)

    def __repr__(self):
        return f"Product({repr(self.name)})"


class Seller(Base):
    __tablename__ = "seller"
    id = Column(Integer, primary_key=True)
    ozon_id = Column(Integer, nullable=False)
    title = Column(String, nullable=True)

    # using this instead of array_agg()
    products = relationship("Product", secondary=seller_product)

    def __repr__(self):
        return (
            f"Seller(title = {repr(self.title)}, products = {repr(self.products)})"
        )


engine.echo = True
with Session(engine) as sess:
    a_seller = sess.scalars(
        select(Seller).options(joinedload(Seller.products))
    ).first()
    """
SELECT seller.id, seller.ozon_id, seller.title, product_1.id AS id_1, product_1.ozon_id AS ozon_id_1, product_1.name 
FROM seller 
LEFT OUTER JOIN (
    seller_product AS seller_product_1 
    JOIN product AS product_1 
    ON product_1.ozon_id = seller_product_1.id_product
) 
ON seller.ozon_id = seller_product_1.id_seller
    """
    print(a_seller)
    """
Seller(title='Harbor Freight', products=[Product('wrench'), Product('hammer')])
    """

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