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