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
Related
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.
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.
I am working in an app with a basic search form with Heroku, but I can't get my sql query to work properly with PostgreSQL, even though this query worked with MySQL. By the way, I tried to paste the logs from Heroku, but it only says that when you search something it renders 500.html.
Here's my model OrdemDeServico with the search action:
def self.search(search)
if search
joins(:cliente).where("clientes.nome LIKE ? OR veiculo LIKE ? OR placa LIKE ? OR ordem_de_servicos.id = ?", "%#{search}%", "%#{search}%", "%#{search}%", "#{search}")
else
where(nil)
end
end
I just installed PostgreSQL locally, and it returned this error when searching:
`PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "Augusto"
LINE 1: ... placa LIKE '%Augusto%' OR ordem_de_servicos.id = 'Augusto')
query:
SELECT "ordem_de_servicos".* FROM "ordem_de_servicos" INNER JOIN "clientes" ON "clientes"."id" = "ordem_de_servicos"."cliente_id" WHERE (clientes.nome LIKE '%Augusto%' OR veiculo LIKE '%Augusto%' OR placa LIKE '%Augusto%' OR ordem_de_servicos.id = 'Augusto') ORDER BY prazo LIMIT 5 OFFSET 0
I finally worked it out a solution. Those who have the same problem here's my code for the model:
def self.search(search)
if search
where("id = ?", search)
joins(:cliente).where("clientes.nome ilike :q or veiculo ilike :q or placa ilike :q", q: "%#{search}%")
else
where(nil)
end
end
I am building a rails app where users can post, must like a form. I want users to be able to search through the posts with a text field, and then all records will be returned where the post content is similar to the user query. For example, a user enters:
'albert einstein atomic bomb'
Then, I want a to run a query where every word is checked, along with the query itself. Something like:
query_result = Hash.new
query_result << Post.where('content ILIKE ?', "%albert%")
query_result << Post.where('content ILIKE ?', "%einstein%")
query_result << Post.where('content ILIKE ?', "%atomic%")
query_result << Post.where('content ILIKE ?', "%bomb%")
query_result << Post.where('content ILIKE ?', "%albert einstein atomic bomb%")
This will not work of course, but I hope you get the idea. Any and all input would be appreciated.
You can use sunspot gem for stuff like this. Once it's setup you can do searches like so
# Posts with the exact phrase "great pizza"
Post.search do
fulltext '"great pizza"'
end
# One word can appear between the words in the phrase, so "great big pizza"
# also matches, in addition to "great pizza"
Post.search do
fulltext '"great pizza"' do
query_phrase_slop 1
end
end
and more. See the info in the link.
What about something like this?
query = 'albert einstein atomic bomb'
sub_queries = query.split("\n") << query
query_results = []
sub_queries.each { |q| query_results << Post.where('content ILIKE ?', "%#{q}%") }
You probably need to flatten the query_results array and uniq to remove duplicates.
in my users model, I have the following:
#users = find(:all, :joins => :instance, :conditions => ['fname LIKE ? or lname LIKE ?', "%#{search}%", "%#{search}%"])
The issue here is that #users only returns data from the user's table, and not the joined instance table. I confirmed this with the SQL query in the logs.
SELECT "users".* FROM "users" INNER JOIN "instances" ON "instances"."id" = "users"."instance_id" WHERE (fname LIKE '%%' or lname LIKE '%%')
How can I make rails SELECT users.* and instance.name ?
Thanks
can you use the :select option and specify "users.*, instance.name"?