[sqlalchemy] efficiently setting many to many collections when I have a sequence of ids.

2010-10-14 Thread Chris Withers

Hi All,

I currently have code that looks like this:

recipients = []
if recipient_ids:
   for id in recipient_ids.split(','):
  recipients.append(
  session.query(recipient.Recipient).filter_by(id=id).one()
  )
else:
recipient_ids = ()
feed.recipients = recipients

Where the models are:

feed_recipient = Table('feed_recipient', Base.metadata,
Column('feed_id', String(length=32), ForeignKey('feed.id')),
Column('recipient_id', Integer, ForeignKey('recipient.id')),
)

class Feed(Base):
__tablename__ = 'feed'
id = Column(String(length=32), primary_key=True)
recipients = relation('Recipient', secondary=feed_recipient)

class Recipient(Base,ComputedMapperArgs):
__tablename__='recipient'
feeds = relation('Feed', secondary=feed_recipient)

It feels like a horribly inefficient way of updating the many-to-many 
relationship. I guess I could just use the sql abstraction layer, but 
that feels like circumventing the ORM without just cause ;-)


Am I missing something? If I have a sequence of ids where I want to 
update the many to many relationship as above, what's the best way of 
doing it?


cheers,

Chris

--
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.



Re: [sqlalchemy] efficiently setting many to many collections when I have a sequence of ids.

2010-10-14 Thread Conor
 On 10/14/2010 01:30 PM, Chris Withers wrote:
 Hi All,

 I currently have code that looks like this:

 recipients = []
 if recipient_ids:
for id in recipient_ids.split(','):
   recipients.append(
   session.query(recipient.Recipient).filter_by(id=id).one()
   )
 else:
 recipient_ids = ()
 feed.recipients = recipients

 Where the models are:

 feed_recipient = Table('feed_recipient', Base.metadata,
 Column('feed_id', String(length=32), ForeignKey('feed.id')),
 Column('recipient_id', Integer, ForeignKey('recipient.id')),
 )

 class Feed(Base):
 __tablename__ = 'feed'
 id = Column(String(length=32), primary_key=True)
 recipients = relation('Recipient', secondary=feed_recipient)

 class Recipient(Base,ComputedMapperArgs):
 __tablename__='recipient'
 feeds = relation('Feed', secondary=feed_recipient)

 It feels like a horribly inefficient way of updating the many-to-many
 relationship. I guess I could just use the sql abstraction layer, but
 that feels like circumventing the ORM without just cause ;-)

 Am I missing something? If I have a sequence of ids where I want to
 update the many to many relationship as above, what's the best way of
 doing it?

You can at least reduce it to a single query:

recipient_id_list = recipient_ids.split(',')
q = session.query(recipient.Recipient)
q = q.filter(recipient.Recipient.id.in_(recipient_id_list))
recipients = q.all()
if len(recipients) != len(recipient_id_list):
invalid_ids = (set(recipient_id_list)
   - set(x.id for x in recipients))
raise StandardError(Invalid recipient ids: %s % sorted(invalid_ids))
feed.recipients = recipients

I wish there was an easy way to do, say:

feed.recipients.ids = recipient_id_list

which would let you avoid querying at all. The downside is you won't
notice invalid ids until the next flush(). Alternatively, you could also
accomplish this via:

feed.recipients = [session.merge(recipient.Recipient(id=id), load=False)
   for id in recipient_id_list]

if session.merge() allowed you to merge newly-created transient objects
with load=False. Maybe add a force parameter to merge, to tell
SQLAlchemy that you really know what you are doing?

-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.