[Dbix-class] trouble with using 'select' in a search clause
Matt S Trout
dbix-class at trout.me.uk
Thu May 18 14:01:55 CEST 2006
John Napiorkowski wrote:
> To be honest I am sure part of my problem is ignorance
> about the best way to use DBIx. So your suggestions
> of any type are useful. I've been using SQL for quite
> a long time and writing a statement like the one I
> show below is a very normal way for me to think. My
> instinct is to try and get all the data I want in a
> single statement, since my training in SQL pushed me
> to consider performance issue.
It's ok, that sort of query is a normal way for me to think too - the only
difference is that I'm able to mentally map DBIC queries to SQL and back
because I've got a pretty good mental model of how they correspond (shockingly
enough :). One of the major design goals of DBIx::Class is to be able to get
the data you want in a single SELECT more often than not, since in
database-backed applications the database is usually the hardest thing to
scale - which usually means you don't need to start hand-setting things via
select and as to achieve that aim. See below for a worked example for your
current case.
> Basically I have a Members table that contains all the
> information about members for my site. My requirement
> is to create a way for members to have an addressbook
> of email addresses and additionally to store
> information about those email addresses on a per
> member basis. I could just create a one to many table
> "members_invitees" with a FK relationship to members,
> but I consider that bad form since it's possible that
> two members could have the same friend in their
> addressbook. So that's why I have a many to many
> relationship here.
That's perfectly sensible. Assuming you have (pseudocoding a bit)
Member has_many member_invitees => MemberInvitee
MemberInvitee belongs_to invitee => Invitee
then
my @members = $schema->resultset('Member')->search(
{ ... <condition> ... },
{ join => { member_invitees => 'invitee' },
prefetch => { member_invitees => 'invitee' },
});
will get you back member objects where
foreach my $member (@members) {
my @invitees = map { $_->invitee } $member->member_invitees;
}
won't result in another trip to the database at all, since the prefetch attr
in the search will cause DBIx::Class to do (effectively)
SELECT members.*, members_invitees.*, invitees.*
FROM members LEFT JOIN members_invitees ON ... JOIN invitees ON ...
WHERE <condition>
in the first place, and all the related objects will be pre-populated as
they're inflated from the results of the SELECT.
> I think that the solution you show can help me. The
> reason I was looking at the select option is that this
> way maps back to the way I would think to do it in
> SQL, but I realize some things about my thinking have
> to change to use DBIx most correctly. Right now I am
> only using this for a few weeks. I'd like to create a
> little chart sometime of common SQL constructs and how
> to replicate them in DBIx; I think such a thing would
> really help newcomers like myself with a big SQL
> background but little or no experience using ORMs.
That would be incredibly handy, yes. We've got a few such examples in the
cookbook but they're all how a given DBIC query maps to SQL - a document
showing a bunch of examples in SQL and how to map them back to DBIC would be
an excellent addition to the manual and much appreciated.
--
Matt S Trout Offering custom development, consultancy and support
Technical Director contracts for Catalyst, DBIx::Class and BAST. Contact
Shadowcat Systems Ltd. mst (at) shadowcatsystems.co.uk for more information
+ Help us build a better perl ORM: http://dbix-class.shadowcatsystems.co.uk/ +
More information about the Dbix-class
mailing list