Thank you very much for the source,

I also learned the term of vertical paradigm and stumble upon the
dictlike.py example in the sqlalchemy source ...

even if yours remains simpler

On Aug 18, 5:05 pm, Conor <conor.edward.da...@gmail.com> wrote:
> On 08/17/2010 11:32 AM, yota wrote:
>
>
>
> > Hello,
>
> > sqlalchemy seems to be the proper tool for my needs but I can't figure
> > out how to design my project or set the ORM properly.
>
> > Let's say, I build a music database, storing tracks and their
> > associated metadata in an sql-like database defined as such :
>
> > TRACK_TABLE ( ident *, url , duration )
> > METADATA_TABLE ( track_ident *, field_name *, field_content )
>
> > (track_ident, field_name) being the primary key for METADATA_TABLE...
>
> > intuitively, a meaningful object for a metadata set would be a
> > dictionary-like object. The name and number of fields being unknown in
> > advance but stored in the METADATA_TABLE as one row per field.
>
> > Here is the question : how may I use the ORM to map
> > a table :
> > 123 / title / waka waka
> > 123 / artist / shakira
> > 123 / featuring / my sister
>
> > to an object like :
> > metadata.title = "waka waka"
> > metadata.artist = "shakira"
> > metadata.featuring = "my sister"
>
> > or a dictionary like :
> > metadata = { "title" : "waka waka", "artist" : "shakira",
> > "featuring" : "my sister" }
>
> > or whatsoever ...
>
> > the solution might also be in rewrite of the sql schema :)
>
> > thanks for your advices
>
> SQLAlchemy supports for this via the attribute_mapped_collection and
> association_proxy classes:
>
> from sqlalchemy.ext.associationproxy import association_proxy
> from sqlalchemy.orm.collections import attribute_mapped_collection
>
> def create_metadata(field_name, field_content):
>     return TrackMetaData(field_name=field_name, field_content=field_content)
>
> class Track(Base):
>     __tablename__ = "track"
>
>     id = Column(Integer, primary_key=True)
>     [...]
>
>     field2metadata = relationship(TrackMetaData,
>                                   backref="track",
>                                   
> collection_class=attribute_mapped_collection("field_name"))
>     field2content = association_proxy("field2metadata",
>                                       "field_content",
>                                       creator=create_metadata)
>
> # I'm only naming this class TrackMetaData to prevent confusion with 
> sqlalchemy.MetaData.
> class TrackMetaData(Base):
>     __tablename__ = "metadata"
>
>     track_id = Column(Integer, ForeignKey("track.id"), primary_key=True)
>     field_name = Column(Unicode(...), primary_key=True)
>     field_content = Column(Unicode(...), nullable=False)
>
> In this way you can access field2content like a dictionary:
>
> artist = track.field2content[u"artist"]
> track.field2content[u"title"] = u"waka waka"
>
> Note that association_proxy does not supply a comparator yet, so if you
> want to join/query on metadata then you need to use the field2metadata
> relationship:
>
> # Find all tracks by artist Shakira.
> q = Session.query(Track)
> q = q.filter(Track.field2metadata.any(and_(TrackMetaData.field_name == 
> u"artist",
>                                            TrackMetaData.field_content = 
> u"Shakira")))
> tracks = q.all()
>
> # Load all tracks, eagerloading their metadata.
> q = Session.query(Track)
> q = q.options(joinedload(Track.field2metadata))
> tracks = q.all()
>
> -Conor

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to