OR condition in query - ruby-on-rails

Try makes the following query:
title = "%#{params[:title]}%"
group = params[:group]
#foods = Food.order('visits_count DESC').where("title ILIKE ? OR group ILIKE ?", title, group).decorate
and in return I get the following error:
ActionView::Template::Error (PG::SyntaxError: ERROR: syntax error at or near "group"
LINE 1: ..."foods".* FROM "foods" WHERE (title ILIKE '%%' OR group ILIK...
^
: SELECT "foods".* FROM "foods" WHERE (title ILIKE '%%' OR group ILIKE '') ORDER BY visits_count DESC):
Any ideas?

Try
"group"
with double-quotes.

Since this is PostgreSQL, you need to quote identifiers using double quotes when case sensitivity is an issue or you're using a keyword as an identifier:
...where('title ILIKE ? OR "group" ILIKE ?', title, group)...
You'd be better off not using a keyword as a column IMO so that you don't have to worry about this sort of thing. I'd go with he quoting for now and then rename the column as soon as possible but that's just me.
While I'm here, you might want to leave out those checks when they don't make sense. This part of your query:
title ILIKE '%%'
will always match when title is not null so you might want to use an explicit not null check or leave it out entirely when there is no title. Similarly for "group" ILIKE '' which only matches when "group" is empty.

Related

ActiveRecord find all records including spesific foreign word (case insensitive)

I would like to write an ActiveRecord query to fetch all records which include specific foreign language words (case insensitive) in the description column of records table.
I think I can use mb_chars.downcase which converts international chars to lower case successfully.
> "ÖİÜŞĞ".mb_chars.downcase
=> "öiüşğ"
However, when I try to use mb_chars.downcase in ActiveRecord query I receive the following error:
def self.targetwords
target_keywords_array = ['%ağaç%','%üzüm%','%çocuk%']
Record.where('description.mb_chars.downcase ILIKE ANY ( array[?] )', target_keywords_array)
end
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: missing FROM-clause entry for table "mb_chars"
I will appreciate if you can guide me how to solve this problem.
You're trying too hard, you should let the database do the work. PostgreSQL knows how to work with those characters in a case-insensitive fashion so you should just let ilike deal with it inside the database. For example:
psql> select 'ÖİÜŞĞ' ilike '%öiüşğ%';
?column?
----------
t
(1 row)
You could say simply this:
def self.targetwords
target_keywords_array = ['%ağaç%','%üzüm%','%çocuk%']
Record.where('description ILIKE ANY ( array[?] )', target_keywords_array)
end
or even:
def self.targetwords
Record.where('description ilike any(array[?])', %w[ağaç üzüm çocuk].map { |w| "%#{w}%" })
end
or:
def self.targetwords
words = %w[ağaç üzüm çocuk]
likeify = ->(w) { "%#{w}%" }
Record.where('description ilike any(array[?])', words.map(&likeify))
end
As far as why
Record.where('description.mb_chars.downcase ILIKE ANY ( array[?] )', ...)
doesn't work, the problem is that description.mb_chars.downcase is a bit of Ruby code but the string you pass to where is a piece of SQL. SQL doesn't know anything about Ruby methods or using . to call methods.

Operator does not exist: character varying[]

Running a simple statement on my User model but keep on getting errors about the operator not matching any of the given arguments. I've never run into anything like this before and don't know how to handle it. I understand I have to perhaps add type casts, but in my POSTGRES database the column keywords is of type array.
#users = User.where("keywords ILIKE ?", "%#{params[:keywords]}%")
How do you handle this?
Exact error message:
ActionView::Template::Error (PG::SyntaxError: ERROR: syntax error at or near "ANY"
LINE 1: SELECT "users".* FROM "users" WHERE (ANY(keywords) LIKE '%an...
^
: SELECT "users".* FROM "users" WHERE (ANY(keywords) LIKE '%angularjs%')):
Thanks!
If you want to search in a postgres array you use the any operator.
Note, this solution assumes params[:keywords] is just a single string like apples or something. It also matches on exact match, not substrings.
#users = User.where('? = ANY(keywords)', params[:keywords])
If you need to use the ILIKE operator you must to something like
#users = User.where("array_to_string(names, ',') ILIKE ?", "%#{params[:keywords]}%")
or if you want to be fancy with regex
#users = User.where("array_to_string(names, ',') ~* ?", params[:keywords])

Single search box produces "ERROR: column reference "name" is ambiguous"

I am trying to use a single search field to filter any column following Railscasts 240. The key piece for defining the search function is in the Contact model.
def self.search(search)
if search
joins(:school).where(['name ILIKE ? OR email ILIKE ? OR school.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
all
end
end
This works without the join and school.name. Contact belongs to school and has a school_id column. The exact error is:
PG::AmbiguousColumn: ERROR: column reference "name" is ambiguous
I'm guessing the ambiguous error is because I am trying to search both contact.name and school.name. Looking for a suggestion to allow searching both without adding another search field or needing the user to specify the search type.
Edit:
Good suggestions below to use contact.name to deal with the ambiguity, but that leads to another error:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "contact"
LINE 1: ...ON "schools"."id" = "contacts"."school_id" WHERE (contact.na...
^
: SELECT "contacts".* FROM "contacts" INNER JOIN "schools" ON "schools"."id" = "contacts"."school_id" WHERE (contact.name ILIKE '%joseph%' OR email ILIKE '%joseph%' OR school.name ILIKE '%joseph%') ORDER BY name asc LIMIT 50 OFFSET 0
I thought this was due to the inner join moving the entire query into the schools table, but the error persists even if I remove the other two queries and ONLY search on school.name.
The ambiguous errors is caused by PG not knowing which name column the query reffers to - contacts.name or schools.name. You can fix it by changing your query to:
joins(:school).where(['contacts.name ILIKE ? OR email ILIKE ? OR schools.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
if columns that same names is more then must add alias
try this, i add contacts.name
def self.search(search)
if search
joins(:school).where(['contacts.name ILIKE ? OR email ILIKE ? school.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
all
end
end

Query using keywords in Rails

I have a Post model, with two attributes: title and content.
I'm trying to make a search form that will look for keywords in the title and/or the content columns.
Let's say there's this record:
title: Foobar bar foo
content: foobar baz foo
Now, if a user inputs the "bar baz" or "baz bar" keywords (order is not important), that record should be found.
What sort of query do I need to accomplish this?
If you are certain the user input is space separated (per keyword):
If you use Postresql this would work:
keywords = user_input.split(" ").map{ |val| "%#{val}%"}
Post.where("title iLIKE ANY ( array[?] )", keywords)
For multiple columns:
Post.where("title iLIKE ANY ( array[?] ) OR content iLIKE ANY ( array[?] )", keywords, keywords)
If you have a Post model with title and content attributes then you can search records like :
Post.where("(title ILIKE (?)) or (content ILIKE (?))","%#{params[:title_param]}%","%#{params[:content_param]}")

Group with ActiveRecord and Postgres

I've seen several answers, but couldn't find anything that helps me
I have a Model which has a country column and a city column.
doing some SQL query, I want to add to that query a group by first country and for each country to group by city
Model.where("name LIKE ?", "%#{query}%").group(["country", "city"])
but I get
PG::GroupingError: ERROR: column "models.id" must appear in the GROUP BY clause or be used in an aggregate function
and I am not sure what to do, since I don't want to group by the ID, just by country and city
I am sure I am missing something here, not sure what
using the fields, as suggested with
Model.where("name LIKE ?", "%#{query}%").group("country, city").select("country, city")
still gives the same error
You should select before grouping
Model.where("name LIKE ?", "%#{query}%")
.select("country, city")
.group("country, city")
If you still have troubles with:
Model.where("name LIKE ?", "%#{query}%").group("country, city").select("country, city")
I guess you have defined a default scope, and you must do this way:
Model.unscoped.where("name LIKE ?", "%#{query}%").group("country, city").select("country, city")
Edited:
If it didn't works, you can do this and publish the output:
Model.where("name LIKE ?", "%#{query}%").group(["country", "city"]).to_sql

Resources