On Wed, Nov 7, 2018 at 1:05 PM <phil.nac...@freenome.com> wrote: > > I need help with structuring the query too. I can implement a query with raw > SQL, but it involves subqueries, and I'm not sure how to translate it to a > column property (or if there's a better way which would avoid the need for a > subquery entirely)
OK see below for a column_property example. as far as not using a column_property, if these Sample objects have relatively small amount of Dataset records each, you could just load them into memory and provide a @property for the count and is_latest features that just look at the length of the list and the latest dates. There's a lot of very efficient eager loading schemes now most particularly "select in" loading. from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declared_attr import datetime Base = declarative_base() class Dataset(Base): __tablename__ = 'datasets' id = Column(Integer, primary_key=True) creation_datetime = Column(DateTime(timezone=False), nullable=False) sample_id = Column(Integer, ForeignKey('samples.id'), nullable=False, index=True) sample = relationship('Sample', uselist=False, innerjoin=True) @classmethod def __declare_last__(cls): cls.is_latest = column_property( exists().where(cls.creation_datetime == select( [func.max(cls.creation_datetime)]).where( cls.sample_id == Sample.id ) ).where(cls.sample_id == Sample.id) ) class Sample(Base): __tablename__ = 'samples' id = Column(Integer, primary_key=True) datasets = relationship('Dataset') num_datasets = column_property( select([func.count(Dataset.id)]).where(Dataset.sample_id == id).correlate_except(Dataset) ) e = create_engine("sqlite://", echo=True) Base.metadata.create_all(e) s = Session(e) s.add_all([ Sample(id=1, datasets=[ Dataset(creation_datetime=datetime.datetime(2018, 11, 7, 11, 52, 0)), Dataset(creation_datetime=datetime.datetime(2018, 11, 7, 10, 52, 0)), Dataset(creation_datetime=datetime.datetime(2018, 11, 7, 9, 52, 0)) ]), Sample(id=2, datasets=[ Dataset(creation_datetime=datetime.datetime(2018, 11, 7, 10, 52, 0)), Dataset(creation_datetime=datetime.datetime(2018, 11, 7, 9, 52, 0)) ]), ]) s.commit() s.close() s1 = s.query(Sample).get(1) print("num datasets in sample 1: %s" % s1.num_datasets) for ds in s1.datasets: print("Dataset creation: %s is latest: %s" % (ds.creation_datetime, ds.is_latest)) assert ds.is_latest == (ds.creation_datetime == datetime.datetime(2018, 11, 7, 11, 52, 0)) > > On Wednesday, November 7, 2018 at 9:54:15 AM UTC-8, Mike Bayer wrote: >> >> On Wed, Nov 7, 2018 at 12:33 PM <phil....@freenome.com> wrote: >> > >> > I have the following two models >> > >> > class Dataset(db.Model): >> > __tablename__ = 'datasets' >> > >> > id = db.Column(db.Integer, primary_key=True) >> > creation_datetime = db.Column(db.DateTime(timezone=False), >> > nullable=False) >> > >> > sample_id = db.Column(db.Integer, db.ForeignKey('samples.id'), >> > nullable=False, index=True) >> > sample = db.relationship('Sample', uselist=False, innerjoin=True) >> > >> > >> > class Sample(db.Model): >> > __tablename__ = 'samples' >> > >> > >> > id = db.Column(db.Integer, primary_key=True) >> > >> > datasets = db.relationship('Dataset') >> > >> > num_datasets = column_property( >> > select([func.count(Dataset.id)]).where(Dataset.sample_id == >> > id).correlate_except(Dataset) >> > ) >> > >> > >> > >> > A sample has many datasets. I would like to add a property "is_latest" to >> > Dataset, probably as a column_property, which is true if the dataset has >> > the latest creation_datetime of the datasets associated with its sample. >> > In other words, if a sample has three datasets, the dataset whose >> > creation_datetime is largest should have is_latest=True and the other two >> > should have is_latest=False >> > >> > If ordering by creation_datetime isn't possible/easy, ordering by primary >> > key is also acceptable. How can I construct this column_property? >> > >> > One of the issues I've encountered while trying to make this work is that >> > there's a circular dependency between the two models. Since the Sample >> > model uses Dataset in its num_datasets property, the Dataset class is >> > currently defined first. But this means that it can't refer to Sample in >> > its own properties >> >> do you need help with the structure of the SQL for is_latest or you're >> just struggling with the definitions for the two column_property >> objects in that they each require the other class? for the latter, >> you need to use a __declare_last__ : >> >> class MyClass(Base): >> # ... >> >> @classmethod >> def __declare_last__(cls): >> cls.is_latest = column_property(....) >> >> >> >> > >> > Thanks for the help >> > >> > This e-mail is private and confidential and is for the addressee only. If >> > misdirected, please notify us by telephone, confirming that it has been >> > deleted from your system and any hard copies destroyed. You are strictly >> > prohibited from using, printing, distributing or disseminating it or any >> > information contained in it save to the intended recipient. >> > >> > -- >> > SQLAlchemy - >> > The Python SQL Toolkit and Object Relational Mapper >> > >> > http://www.sqlalchemy.org/ >> > >> > To post example code, please provide an MCVE: Minimal, Complete, and >> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> > description. >> > --- >> > You received this message because you are subscribed to the Google Groups >> > "sqlalchemy" group. >> > To unsubscribe from this group and stop receiving emails from it, send an >> > email to sqlalchemy+...@googlegroups.com. >> > To post to this group, send email to sqlal...@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> > For more options, visit https://groups.google.com/d/optout. > > > This e-mail is private and confidential and is for the addressee only. If > misdirected, please notify us by telephone, confirming that it has been > deleted from your system and any hard copies destroyed. You are strictly > prohibited from using, printing, distributing or disseminating it or any > information contained in it save to the intended recipient. > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.