Flask SQLAlchemy - Как запросить БД для объектов, соответствующих атрибутам связанного объекта? - PullRequest
0 голосов
/ 27 февраля 2020
from app import db


terpenes = db.Table('tags', 
                    db.Column(
                        'terpene_id', db.Integer, 
                        db.ForeignKey('terpene.id'), 
                        primary_key=True
                    ),
                    db.Column(
                        'strain_id', db.Integer, 
                        db.ForeignKey('strain.id'), 
                        primary_key=True
                    )
                    )


class Compound(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(96), nullable=False)
    percent_concentration = db.Column(db.Numeric(precision=10, scale=20), nullable=True)
    terpenes = db.relationship('Terpene', backref='compound', lazy=True)

    def __repr__(self):
        return f'<Compound {self.name} @{self.percent_concentration}%>'.format(self.name, self.percent_concentration)


class Terpene(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    compound_id = db.Column(db.Integer, db.ForeignKey('compound.id'), nullable=False)

    @property
    def serialize(self):
        return {
            'id': self.id,
            'compound_id': self.compound.name
        }

    def __repr__(self):
        return '<Terpene %r>' % self.compound.name


class Strain(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(96), unique=True, nullable=False)
    terpenes = db.relationship('Terpene', secondary=terpenes, lazy='subquery', backref=db.backref('strains', lazy=True))

    @property
    def serialize(self):
        return {
            'id': self.id,
            'name': self.name,
            'terpenes': self.serialize_many2many,
        }

    @property
    def serialize_many2many(self):
        return [i.serialize for i in self.terpenes]

    def __repr__(self):
        return '<Strain %r>' % self.name

У меня есть приложение Flask, в котором у меня есть простой объект "Штамм" с полем "многие ко многим", установленным для другого объекта, Терпена.

Каждый Терпен имеет поле FK для другого объекта , Соединение.

Каждый штамм имеет 5 терпенов.

Я хочу выбрать штамм и запросить базу данных с ORM, чтобы получить любые другие штаммы, которые имеют по крайней мере 3 соответствующих терпена к штамму. selected.

Как реализовать часть запроса с помощью ORM?

Пример: штамм "A" -линалоол-мирцен -кариофиллен-пинен-лимонен

штаммы запрашивается возвращаемое ORM (у которого есть по крайней мере 3 из терпенов в штамме "A")

Штамм "B" -линалоол-Мирцен-кариофиллен-геранинол-карен

Штамм " c -кариофиллен-пинен-лимонон-геранинол-карен

1 Ответ

1 голос
/ 02 марта 2020

Начните с выбора соединения штамма, терпена и соединения. Затем отфильтруйте по терпенам А, сгруппируйте по штаммам и, наконец, убедитесь, что в группе есть хотя бы 3 совпадения:

In [19]: strain_a_terpenes = db.session.query(Compound.name).\
    ...:     join("terpenes", "strains").\
    ...:     filter(Strain.name == "A").\
    ...:     subquery()
    ...: 

In [20]: db.session.query(Strain).\
    ...:     join("terpenes", "compound").\
    ...:     filter(Compound.name.in_(strain_a_terpenes)).\
    ...:     group_by(Strain.id).\
    ...:     having(db.func.count() >= 3).\
    ...:     all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...