I am using rails with a postgresql db, and I would like to know which is the best solution, in getting all the rows which are similar with a string.
string format: domain.com or domain.com/uk or subdomain.domain.com
db column format : http://www.test.com/All-test/test1/test2-test3/
So I would like to get from my table all the rows which are matching with my string.
Currently I have a script which is going through all the rows in my table, and taking the column values, from where it takes the host and compares it with the string.
Thank you
Looks like the LIKE function is what you want to use. You can use in in an ActiceRecord query like this:
search_string = "domain.com"
YourModel.where("db_column LIKE ?", "%#{search_string}%").first
You might need to refine the search, but the link above should give you all the tools you need
Related
Hi im fetching the user input and displaying the records that matches the condition, my query will look like
customers = customers.where('customers.contact_num ilike :search', {search: "%#{options[:search_contact]}%"})
here in db the contact number is stored in string with the format (091)-234-5678 like that
on while searching the user on basis of contact number if i search like this
091 it filters the number correctly, but while searching like 0912, it doesn't display record due to the braces, so how to modify the query to neglect the ) and - while searching..
As im new to the domain please help me out
thanks in advance
What about using REGEXP_REPLACE to remove all non-digit chars from the search - something like below?
customers = customers.where("REGEXP_REPLACE(customers.contact_num,'[^[:digit:]]','','g') ilike :search", {search: "%#{options[:search_contact]}%"})
Changing the query is hard. Let's not do that.
Instead right a quick script to transforms your numbers into
1112223333 form. No formatting at all. Something like:
require 'set';
phone = "(234)-333-2323"
numbers = Set.new(["1","2","3","4","5","6","7","8","9","0"])
output = phone.chars().select{|n| numbers.include?(n)}.join("")
puts output
=> "2343332323"
Then write a little function to transform them into display form for use in the views.
This will make your query work as is.
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.
I have array of strings:
a = ['*#foo.com', '*#bar.com', '*#baz.com']
I would like to query my model so I will get all the records where email isn't in any of above domains.
I could do:
Model.where.not(email: a)
If the list would be a list of strings but the list is more of a regexp.
It depends on your database adapter. You will probably be able to use raw SQL to write this type of query. For example in postgres you could do:
Model.where("email NOT SIMILAR TO '%#foo.com'")
I'm not saying thats exactly how you should be doing it but it's worth looking up your database's query language and see if anything matches your needs.
In your example you would have to join together your matchers as a single string and interpolate it into the query.
a = ['%#foo.com', '%#bar.com', '%#baz.com']
Model.where("email NOT SIMILAR TO ?", a.join("|"))
Use this code:
a = ['%#foo.com', '%#bar.com', '%#baz.com']
Model.where.not("email like ?",a.join("|"))
Replace * to % in array.
I don't know the name for this kind of search, but I see that it's getting pretty common.
Let's say I have records with the following file names:
'order_spec.rb', 'order.sass', 'orders_controller_spec.rb'
If I search with the following string 'oc' I would like the result to return 'orders_controller_spec.rb' due to match the o in orders and the c in controller.
If the string is 'os' then I'd like all 3 to match, 'order_spec.rb', 'order.sass', 'orders_controller_spec.rb'.
If the string is 'oco' then I'd like 'orders_controller_spec.rb'
What is the name for this kind of search and how would I go about getting this done in Postgresql?
This is a called a subsequence search. One simple way to do it in Postgres is to use the LIKE operator (or several of the other options in those docs) and fill the spaces between your letters with a wildcard, which for LIKE is %. To match anything with an o followed by an s in the words column, that would look like this:
SELECT * FROM table WHERE words LIKE '%o%s%';
This is a relatively expensive search, but you can improve performance with a varchar_pattern_ops or text_pattern_ops index to support faster pattern matching.
CREATE INDEX pattern_index ON table (words varchar_pattern_ops);
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(',')