rails find records containing specific word [duplicate] - ruby-on-rails

This question already has answers here:
Rails: How to find_by a field containing a certain string
(5 answers)
Closed 7 years ago.
I'm looking for a way to find all entries in a database containing a specific string. I know it's possible to iterate over every entry and see if a string matches but with a growing database i'd rather not do that. I'm wondering if there is a Rails way of doing it.
something like
Table.where("content containsWord ?", "string")
So a function find all records containing a specific string.
Does anyone know a way to do this?
update
duplicate of Rails: How to find_by a field containing a certain string

You can try this
search_term = "string"
tables = Table.where("tables.content LIKE ?", "%#{search_term}%")
or, if you want to ignore case sensitiveness, then do this
search_term = "string"
tables = Table.where("lower(content) LIKE lower(?)", "%#{search_term}%")
Hope this helps!

Related

Activerecord query against array column using wildcard

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.

Query in a string column for one of the value in an array like multiple OR (using full text search)

In a rails 4 app, in one model I have a column containing multiple ids as a string with comma separated values.
"123,4568,12"
I have a "search" engine that I use to retrieve the records with one or many values using the full text search of postgresql I can do something like this which is very useful:
records = MyModel.where("my_models.col_name ## ?", ["12","234"])
This return all the records that have both 12 and 234 in the targeted column. The array comes from a form with a multiple select.
Now I'm trying to make a query that will find all the records that have either 12 or 234 in there string.
I was hopping to be able to do something like:
records = MyModel.where("my_models.col_name IN (?)", ["12","234"])
But it's not working.
Should I iterate through all the values in the array to build a query with multiple OR ? Is there something more appropriate to do this?
EDIT / TL;DR
#BoraMa answer is a good way to achieve this.
To find all the records containing one or more ids referenced in the request use:
records = MyModel.where("my_models.col_name ## to_tsquery(?)", ["12","234"].join('|'))
You need the to_tsquery(?) and the join with a single pipe |to do a OR like query.
To find all the records containing exactly all the ids in the query use:
records = MyModel.where("my_models.col_name ## ?", ["12","234"])
And of course replace ["12","234"] with something like params[:params_from_my_form]
Postgres documentation for full text search
If you already started to use the fulltext search in Postgres in the first place,I'd try to leverage it again. I think you can use a fulltext OR query which can be constructed like this:
records = MyModel.where("my_models.col_name ## to_tsquery(?)", ["12","234"].join(" | "));
This uses the | operator for ORing fulltext queries in Postgres. I have not tested this and maybe you'll need to do to_tsvector('my_models.col_name') for this to work.
See the documentation for more info.
Suppose your ids are :
a="1,2,3,4"
You can simply use:
ModelName.find(a)
This will give you all the record of that model whose id is present in a.
I just think a super simple solution, we just sort the ids in saving callback of MyModel, then the query must be easier:
class MyModel < ActiveRecord::Base
before_save :sort_ids_in_col_name, if: :col_name_changed?
private
def sort_ids_in_col_name
self.col_name = self.col_name.to_s.split(',').sort.join(',')
end
end
Then the query will be easy:
ids = ["12","234"]
records = MyModel.where(col_name: ids.sort.join(',')

ActiveRecord "lower(column_name)" is still case sensitive. (MySql2, Rails)

I am using MySql2 in my Rails application. I am trying to make an activerecord query that returns all records that have specified fields containing a string. I have read that downcasing my input and then using lower(column_name) LIKE 'string' should do the trick, but this does not appear to work. My query is exactly as follows:
search = params[:search].to_s.downcase
#current_user.patients.where("lower(last_name) LIKE ? OR lower(first_name) LIKE ? OR lower(identifier) LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%")
Let's say I have a record with the last name "Abbott". When my search param is "Abb" or "bot", this record is returned. However, when the search param is "abb" or "Bot", nothing is returned. It appears that the query is still case sensitive??
I have looked all over and cannot seem to find an answer. I have read multiple times that lower(column_name) should work, but it does not.
Any help is appreciated. Thanks!
I figured it out. It was indeed because the fields were stored as binary values (thanks Vincent). By casting the binary fields as a CHARs, I was able to case-insensitively compare them:
#current_user.patients.where("CAST(last_name AS CHAR) LIKE ? OR ...

How can I query all records that don't have a specific association without loading them all into memory?

If I want a list of all the shops that are open on Sunday, I do
Shop.includes(:opening_times).where("opening_times.day =?", 'Sunday')
Is there any way to get a list of all the shops that are closed on Sundays? That is, all the shops that are not associated with a record where the day column is 'Sunday'?
I asked this question here and accepted an answer. However, now my database is getting too big to solve this by loading all the open shops into memory first. Is there a way to do this without first getting an array of all the open shops and passing that array back to the database?
There could be a more Railsy way, but with a single query (and subquery):
Shop.where("shop_id NOT IN (select opening_times.shop_id from opening_times where opening_times.day = 'Sunday')")
Or, based on the linked question, you could improve by using pluck:
shop_ids = Shop.includes(:opening_times).where("opening_times.day = ?", 'Sunday').pluck(:id)
shops = Shop.where("id NOT IN(?)", shop_ids)
The current method you're using (map(&:id)) is instantiating objects for every row, whereas pluck(:id) will perform a select id query.
A faster way without map would be to pluck the id's instead.
open = Shop.includes(:opening_times).where(opening_times: { day: 'Sunday' }).pluck(:id)
closed = Shop.where.not(id: open)
I'm not sure I understand what you're asking, but I'll have a go.
When I need to query for objects that don't have an association, I normally created a counter cache for the # of associated objects and query that. So, in the end, your query would look like this:
Shop.include(:opening_times).where("opening_times.sunday_count", 0)

Better Way to Randomize (Ruby/Rails 3) [duplicate]

This question already has answers here:
Rails select random record
(8 answers)
Closed 5 years ago.
I'm currently using:
#users = User.order("RANDOM()").limit(6)
to generate a list of 6 random users - however, this method takes a 1200ms toll on page load times. Is there a faster/more efficient way to call 6 random users?
I ended up using the method described here:
Rails select random record
#ramc - Thank you for your comment. Load times are now much faster :)
Assuming auto increment ids, starting from 0 and that User objects are never deleted, the following should be quite fast:
#users = (0..5).map { User.find(rand * User.count) }
Have you tried using a random offset & limit?
class User < ActiveRecord::Base
def self.random num = 1
num.times.map { offset(rand(count)).limit(1) }
end
end
#users = User.random(6)
I've used something similar to get single random instances from AR. You'd have to make it a bit smarter if you wanted to guarantee unique results.
You could get a random Page of users instead. Consider this pagination call using Kaminari
User.order('created_at').page(rand(User.count)).per(6)
This will fire one count query and one query for the page of 6 Users
You could try using array shuffle instead of using mysql random as it can be slow:
#users = User.all.shuffle[0..5]
After all, a collection of ActiveRecord objects is still just an Array

Resources