0
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

I have a Flask application where I have a simple Strain object with a many-to-many field set to another Object, Terpene.

Each Terpene has a FK field to another object, Compound.

Each Strain has 5 terpenes.

I want to select a Strain and have query the database with the ORM to retrieve any other Strains which have at least 3 matching terpenes to the Strain selected.

How do I implement the query part of this with the ORM?

Example: Strain "A" -linalool -myrcene -caryophyllene -pinene -limonene

Strains queried with ORM to be returned (which have at-least 3 of the terpenes in Strain "A")

Strain "B" -linalool -myrcene -caryophyllene -geraninol -carene

Strain "c" -caryophyllene -pinene -limonene -geraninol -carene

1 Answer 1

1

Start by selecting the join of strain, terpene, and compound. Then filter by A's terpenes, group by strain, and finally check that the group has at least 3 matches:

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()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.