Hi I'm working on a project and I need to take result of two database queries and combine them into one ActiveRecord_AssociationRelation, at the moment I have:
results.where(pos_or_neg: "neg").order("value DESC") + (results.where(pos_or_neg: "pos").order("value ASC"))
However this returns an array which doesn't work as I need to do more processing afterwards. I've tried:
results.where(pos_or_neg: "neg").order("value DESC").merge(results.where(pos_or_neg: "pos").order("value ASC"))
but this only seems to return the half of the results.
Thanks
results.order("pos_or_neg ASC,case when pos_or_neg="neg" then value else -1*value end DESC")
I believe using merge is the equivalent of an AND query in SQL. What you are looking for is an OR query.
Since Rails 5 this is one of the Active Record query methods that you can use!
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-or
Try to replace your .merge with .or and see if that works better
Related
I'm using the following raw Postgres SQL in my where() call to find records where some_date is two days from now:
SomeModel.where('date(some_date) - date(NOW()) = 2')
Can it be written using pure ActiveRecord syntax without raw SQL?
This should work, haven't tested it though.
SomeModel.where('date(some_date) = ?', 2.days.ago.to_date)
#or
SomeModel.where('some_date::date = ?', 2.days.ago.to_date)
If you want it to be any purer, without the date sql function, I'm not seeing it, at least not without creating a db view.
So let's say i have a Customer model with array column phones.
It's pretty easy to find all customers with given phone
Customer.where('? = ANY(phones)', '+79851234567')
But i can't figure out how to use LIKE with wildcard when i want to find customers with phones similar to given one, something like:
Customer.where('ANY(phones) LIKE ?', '+7985%')
I'm using PostgreSQL 9.5 and Rais 4.2
Any ideas?
I think, first of all, its better to use second table phones with fields customer_id, phone_number. I think it's more rails way ). In this way you can use this query
Phone.where("phone_number LIKE ?", '%PART%').first.customer
If you serialize your array in some text field, by example JSON, you should use % on both sides of your pattern:
Customer.where('phones LIKE ?', '%+7985%')
If you have an array in your database, you should use unnest() function to expand an array to a set of rows.
Can you try this
Customer.where("array_to_string(phones, ', ') like ?", '+7985%')
I believe this will work.
Can someone briefly explain to me the difference in use between the methods uniq and distinct?
I've seen both used in similar context, but the difference isnt quite clear to me.
Rails queries acts like arrays, thus .uniq produces the same result as .distinct, but
.distinct is sql query method
.uniq is array method
Note: In Rails 5+ Relation#uniq is deprecated and recommended to use Relation#distinct instead.
See http://edgeguides.rubyonrails.org/5_0_release_notes.html#active-record-deprecations
Hint:
Using .includes before calling .uniq/.distinct can slow or speed up your app, because
uniq won't spawn additional sql query
distinct will do
But both results will be the same
Example:
users = User.includes(:posts)
puts users
# First sql query for includes
users.uniq
# No sql query! (here you speed up you app)
users.distinct
# Second distinct sql query! (here you slow down your app)
This can be useful to make performant application
Hint:
Same works for
.size vs .count;
present? vs .exists?
map vs pluck
Rails 5.1 has removed the uniq method from Activerecord Relation and added distinct method...
If you use uniq with query it will just convert the Activerecord Relaction to Array class...
You can not have Query chain if you added uniq there....(i.e you can not do User.active.uniq.subscribed it will throw error undefined method subscribed for Array )
If your DB is large and you want to fetch only required distinct entries its good to use distinct method with Activerecord Relation query...
From the documentation:
uniq(value = true)
Alias for ActiveRecord::QueryMethods#distinct
Its not exactly answer your question, but what I know is:
If we consider ActiveRecord context then uniq is just an alias for distinct. And both work as removing duplicates on query result set(which you can say up to one level).
And at array context uniq is so powerful that it removes duplicates even if the elements are nested. for example
arr = [["first"], ["second"], ["first"]]
and if we do
arr.uniq
answer will be : [["first"], ["second"]]
So even if elements are blocks it will go in deep and removes duplicates.
Hope it helps you in some ways.
Given I got User.attachments and Attachment.visits as an integer with the number count.
How can I easily count all the visits of all images of that user?
Use ActiveRecord::Base#sum:
user.attachments.sum(:visits)
This should generate an efficient SQL query like this:
SELECT SUM(attachments.visits) FROM attachments WHERE attachments.user_id = ID
user.attachments.map{|a| a.visits}.sum
There's also inject:
user.attachments.inject(0) { |sum, a| sum + a.visits }
People generally (and quite rightly) hate inject, but since the two other main ways of achieving this have been mentioned, I thought I may as well throw it out there. :)
The following works with Plain Old Ruby Objects, and I suspect the following is marginally faster than using count += a.visits, plus it has an emoticon in it:
user.attachments.map(&:visits).inject(:+)
So I have two separate queries:
tagged_items = Item.tagged_with(params[:s], :on => :tags)
searched_items = Item.find(:all, :conditions => ["MATCH(title) AGAINST (? IN BOOLEAN MODE)", "*#{params[:s]}*"])
The first tagged_items is using the acts_as_taggable_on plugin to find all the items tagged with XYZ.
The second, searched_items, is used to search the items table for the search term.
So, how could I combine (and avoid duplicates) the results of these two?
Check out named_scope. The second query can be converted to named_scope easily, I'm not sure about the first one, but if you can rewrite it using find, you're home.
http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html
items = (tagged_items + searched_items).unique
But it would be much better if you could fetch them with single query.
This approach...
#items = tagged_items | searched_items
...would make more sense if you're looking to use the results of these queries in a View, instead of working with an Array, and accomplishes the de-duplication as well.