[LRUG] association finder query problem
Matthew Rudy Jacobs
matthewrudyjacobs at gmail.com
Sat May 24 16:01:26 PDT 2008
That's fine
(although I have a feeling it'll break in 2.1, with the changes to
eager-loading, if Freddy is right)
But, I just feel like we're cheating using :include, when our goal is not
actually to :include.
And, it'll have us ending up with a "Monitor" with a random set of
"features" eager loaded
(all those that are "big", I think?)
Perhaps the best way, if we don't mind doing multiple queries is;
big_ids = Feature.find(:all, :select => "DISTINCT monitor_id",
:conditions => {:name => "big"}).map(&:monitor_id)
white_ids = Feature.find(:all, :select => "DISTINCT monitor_id", :conditions
=> {:name => "white"}).map(&:monitor_id)
Monitor.find(big_ids & white_ids, :include => :features)
Although,
I don't really understand why the models are set up like this.
Feels like,
Monitor
MonitorFeature
Feature
2008/5/24 Ben Griffiths <bengriffiths at gmail.com>:
> I don't know your application - particularly whether that function is
> frequently called, nor the size and cardinality of your database, -
> but it might be perfectly reasonable to just use the array
> intersection operator (&). Something along the lines of:
>
> monitors = Monitor.find(:all, :include=>:features :conditions => "name
> = 'big'") & Monitor.find(:all, :include=>:features :conditions =>
> "name = 'white'")
>
> The two queries and unnecessary marshaling, and so on may not be an
> issue (only you will know) - and it's much more readable and
> intentional than jumping through sql loops.
>
> Actually, having said all that, I don't know if this works with rails
> object arrays, should do though? Maybe you could try it and let me
> know!
>
> Ben
>
> On 5/24/08, Matthew Rudy Jacobs <matthewrudyjacobs at gmail.com> wrote:
> > 2008/5/24 Xin Zheng <xin at zenpow.com>:
> >> I want to find a Monitor that is BOTH white and big.
> >>
> >>My first shot at this:
> >>find(:all, :include => :features, :conditions => ["name IN ('white',
> >>'big')" )
> >>
> >>But this query will find Monitors that's EITHER white or big.
> >
> >
> > Yeah,
> > the short answer is;
> > "that's exactly what you've asked it to do"
> >
> > ===========
> > Your db
> > ===========
> > - Monitor#1
> > -- Feature#1 = big
> > -- Feature#2 = white
> > -- Feature#3 = small
> >
> > - Monitor#2
> > -- Feature#4 = big
> >
> > - Monitor#3
> > -- Feature#5 = white
> >
> > - Monitor#4
> > -- *no features*
> > ===========
> >
> > Doing an include gets you a left outer join on "features"
> > which creates a new line for each feature.
> > ===========
> > - Monitor#1 & Feature#1(big)
> > - Monitor#1 & Feature#2(white)
> > - Monitor#1 & Feature#3(small)
> > - Monitor#2 & Feature#4(big)
> > - Monitor#3 & Feature#5(white)
> > - Monitor#4 & *no feature*
> > ===========
> >
> > Then you say
> > "name IN (white, big)"
> > ===========
> > this grabs all those lines which satisfy your requirement
> > ===========
> > - Monitor#1 & Feature#1(big)
> > - Monitor#1 & Feature#2(white)
> > - Monitor#2 & Feature#4(big)
> > - Monitor#3 & Feature#5(white)
> > ===========
> >
> > Hence,
> > you don't get what you want.
> >
> > And,
> > you don't actually intend to ":include" these features anyway, (if you
> do,
> > then my solution is wrong)
> > you're just using the :include, because it does the join automatically.
> >
> > The right solution is debatable;
> > can do it with subqueries, or a double "inner join"
> >
> > but I think subqueries are the right way,
> > they look dirty, but it's exactly what you're asking for.
> >
> > Hopefully MySQL will optimise it correctly.
> >
> > condition_bit = "EXISTS(SELECT * FROM features WHERE monitor_id =
> > monitors.id & features.name = ?)"
> > condition_string = ([condition_bit]*2).join(" AND ")
> > conditions = [condition_string, "big", "white"]
> > Monitor.find(:all, :conditions => conditions)
> >
> > my friend Freddy Cheung wrote a nice blog post about similar stuff:
> > http://www.spacevatican.org/2008/4/29/include-and-conditions
> >
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20080525/b3a1000d/attachment-0003.html>
More information about the Chat
mailing list