I am having trouble searching a string by the first letters. For example, if I have "animal", "ant", and "abs" in my database, I would like a query of "an" to return "animal" and "ant" (case insensitive). I got this working just fine with sqlite3:
Thing.where("name LIKE ?", params[:query] + '%')
However, this does not work in PostgreSQL (database used in pushing to Heroku). What is the correct query using PostgreSQL?
In PostgreSQL, you have to use ILIKE instead of LIKE to do a case-insensitive pattern match.
Your query will be:
Thing.where("name LIKE '?%'", params[:query])
This makes the query case insensitive:
Thing.where("lower(name) LIKE '?%'", params[:query].to_s.downcase)
If your production uses Postgres, I recommend development does it also, to prevent a further error like this!
Related
I'm new to ROR and trying to implement search in PostgreSQL database using Active Record. I've found that to make search case insensitive I can use ILIKE operator instead of equals and LIKE but not sure what to do when I need to use IN operator.
I'm getting a field name and a collection of values which I need to check and case sensitive search works like that:
records = records.where(filter['fieldName'] => filter['value'])
where filter['value'] is an array.
Is there a way to update that line to make it case insensitive?
If no then I believe the only way is to loop through that array and split IN into many OR operations and use ILIKE for every single value in that array(however I'm not sure how to use OR with Active Record)?
Thanks!
records.where("lower(#{filter['fieldName']}) in (?)", filter['value'].map(&:downcase))
This is what worked for me:
records = records.where('"' + filter['fieldName'] + '"' +
" ILIKE ANY ( array[?] )", filter['value'].map {|value| "%#{value}%" })
Try this ......
records.where("lower(#{filter['fieldName']}) in ?", filter['value'].map(&:downcase))
Hope this will work for you.
I have a sql query which I have written in the following way:
SELECT "books".* FROM "books" WHERE (title LIKE '%intro%' OR isbn LIKE '%intro%' or status like '%intro%' or author like '%intro%' or description like '%intro%')
In my rails model I wrote the following way:
def self.search(query)
where(['title LIKE ? OR isbn LIKE ? or status like ? or author like ? or description like ?', "%#{query}%", "%#{query}%","%#{query}%","%#{query}%","%#{query}%"])
end
This works on my sqlite3 database and returns all rows with the query "intro".
However in my postgres database it returns only one row. Could some one suggest me a way.
Contents of my table:
id isbn title description author status
2 15 Introduction to english Introduction to english veena kapoor available
3 16 Introduction to hindi Introduction to hindi rastogi vinayak available
4 17 Introduction to sanskrit Introduction to sanskrit edward solomon available
The condition WHERE title LIKE '%intro%' (for example) won't match the value 'Introduction to english' because LIKE is case-sensitive in Postgres. You must ILIKE to do a case-insensitive match.
This may be a problem, since ILIKE doesn't work in SQLite. Take a look at this question for some potential solutions: Generic Ruby solution for SQLite3 "LIKE" or PostgreSQL "ILIKE"? The best solution (as proffered by the top-rated answer there) is to use the same database (Postgres) in both development and production.
So let's say I search for 'Blerg'. And I have a item with the name SomethingblergSomething.
If I do an ILIKE search in postgres (and rails) like this:
where("name ILIKE ?", "%#{ 'Blerg' }%")
It will return the result 'SomethingBlergSomething' because it contains Blerg.
Is there a way to make the faster tsvector do a similar style of searching inside a word:
where("(to_tsvector('english', name) ## to_tsquery(?))", ('Blerg' + ':*'))
The above query will not return 'SomethingBlergSomething'.
So how do I make tsvector act like ILIKE when searching inside words.
Are you aware of trigram search, provided by the additional module pg_trgm? That seems more appropriate for your use case than text search.
With a trigram index in place (GIN or GiST) you can use your original ILIKE predicate and get index support for it. You need Postgres 9.1+ for that.
Details:
PostgreSQL LIKE query performance variations
Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL
What's the easiest way to do a quick wildcard search on a field from the console? I don't care against guarding against SQL injection.
I'm using PostgreSQL.
Searching for title with strings containing "emerging'
This works but is somewhat cumbersome. Curious if there was a shorthand?
Product.where("title ## :q", q: "emerging")
Equally cumbersome but no longer appear to work for me in Rails 4:
Product.where("title ILIKE ?", "emerging")
Product.where("title ilike :q", q: "emerging")
I guess I'm looking for something like Product.where(title: "*emerging*")
This should do it:
word = 'emerging'
Product.where('title ILIKE ?', "%#{word}%")
The ILIKE makes the search not sensitive to the case (PostgreSQL feature!)
the "%" wildcard makes the search match every product having a title containing "word" inside with (or without) stuff before and/or after.
Use LIKE, like this:
Product.where('title LIKE ?', '%emerging%')
I have an application where I want to migrate from MetaWhere to Squeel in preparation for an upgrade to Rails 3.1.
This has been mostly a simple process but I have one case that causes me a bit of problems. The problem is that I have both the field and the value specified as variables. In my MetaWhere queries I could simply create symbols out of the field names and then use that in the query but Squeel does not use symbols but instead relies on instance_eval and I cannot figure out how to create a similar query using that...
An illustration of the original query could be:
Article.where("#{field_name}".to_sym.matches => '%' + field_value + '%')
How do I create a similar query in Squeel?
I know I can specify that I want to use the legacy symbol functionality but I would rather fully convert to the new syntax.
This works:
Article.where{article.send(field_name) =~ '%' + field_value + '%'}
The lowercase 'article' being the table name.