how can I use like query in ruby with sinatra? - ruby

Here's the query I tried:
#blogs = DB[:blogs].where(:title => params[:s_txt]).reverse_order(:id)
In this query, I'd like to find blogs in my database. I also need to create a query that gives users more results. How can I do this?

It is better to use dynamic parameters to avoid SQL injection:
#blogs = DB[:blogs].where("title LIKE ?", "%#{params[:s_txt]}%").reverse_order(:id)
or
#blogs = DB[:blogs].where("title LIKE :text", text: "%#{params[:s_txt]}%").reverse_order(:id)
You can easily add more parameters to this:
#blogs = DB[:blogs].where("title LIKE ? OR content LIKE ?", "%#{params[:s_txt]}%", "%#{params[:s_txt]}%").reverse_order(:id)
or
#blogs = DB[:blogs].where("title LIKE :text OR content LIKE :text", text: "%#{params[:s_txt]}%").reverse_order(:id)

I also had this problem and only found this solution
#blogs = DB[:blogs].where("title LIKE '%#{params[:s_txt]}%'").reverse_order(:id)
Curious if there are better ways..
Searching in two fields is repeating the LIKE and seperating by AND or OR
#blogs = DB[:blogs].where("title LIKE '%#{params[:s_txt]}%'
or comment LIKE '%#{params[:c_txt]}%'").reverse_order(:id)
or do it like this
#blogs = DB[:blogs].where("title||comment LIKE '%#{params[:s_txt]}%'").reverse_order(:id)
Tested in Sqlite and it works. One advise: in lage tables you 'd better drop the first % if possible because the database will do a full table scan otherwise without using indexes but you can find all that stuff in the sql questions.

Related

How to properly perform like queries with Quickbase

I am working with quicktable queries and everything seems to be fine.
Now I want to perform queries using like operators. For instance in PHP I can do something like:
$data ='content to search';
$stmt = $db->prepare('SELECT * FROM members where name like :name OR email like :email limit 20');
$stmt->execute(array(
':name' => '%'.$data.'%',
':email' => '%'.$data.'%',
));
Now in quick table, I have tried using CT, EX or HAS parameter etc with OR Operators. Only CT gives nearby result but not exact as per code below.
//Email = 7
//name =8
{
"from": "tableId",
"where": "{7.CT.'nancy#gmail.com'}OR{8.CT.'nancy'}"
}
Is there any way I can obtain a better search with like operators with Quickbase. The documentation here does not cover that.
CT is the closest string comparison operator in Quick Base to LIKE in SQL, but since you can't use wildcards in Quick Base queries you might need to group multiple query strings to achieve the same result. The is also a SW operator that can sometimes come in helpful for comparing parts of a strings.

Ecto where like query acts like where ==

I'm trying to get an ecto like query working like this:
def find(searchterm) do
query = from c in Contact,
#where: fragment("? % ?", c.company_name, ^searchterm),
where: like(c.company_name, ^searchterm),
contacts = Repo.all(query)
{:ok, contacts}
end
In my table, I have a company_name "Asymptote". Using where: like/2 my query looks like this:
SELECT c0."id", c0."company_id", c0."company_name" FROM "contacts" AS c0 WHERE (c0."company_name" LIKE $1) ["Asym"] (1.0ms)
when the pg_trm search uncommented, it looks like this:
SELECT c0."id", c0."company_id", c0."company_name" FROM "contacts" AS c0 WHERE (c0."company_name" % $1) ["Asym"] (1.0ms)
As far as I can see, the queries look good, but there are no results. Since I added the index after adding "Asymptote" to the database, I expect that is why it isn't found in the pg_trm index, but why won't like/2 or ilike/2 work? When entering in the full name "Asymptote", I am able to find the record.
I faced some similar problem. Unfortunately I had no pg_trgm available. I used the LIKE as in:
from candidate in query,
where: like(candidate.first_name, ^("%#{text}%"))
This matched the text in any place of the candidate.first_name.
With the help of Mitchell Henke of Rokkincat, here's a way to get pg_trgm working with custom match percentages:
def find(searchterm) do
limit = 0.1
query = from c in Contact,
where: fragment("similarity(?, ?) > ?", c.company_name, ^searchterm, ^limit),
#where: like(c.company_name, ^searchterm),
contacts = Repo.all(query)
{:ok, contacts}
end
But I still can't get like/2 working. Also, I don't see where in Ecto source this function exists.

Rails combine multiple activerecord relations

I want to union multiple active record relation
For example,
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
I want to combine these two relation.
not merge, merge is
apple_companies.merge(banana_companies)
=> Company.where("name like ? and name like ?", "%apple%","%banana%")
I want to
Company.where("name like ? or name like ?", "%apple%","%banana%")
afterward,
I will code
companies = Company.none
company_name_list.each do |name|
like = "%"+name+"%"
companies += Company.where("name like ?",like)
end
but code which I wrote make companies to array.....
So I cannot order and page to companies... :(
thank you
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
apples = apple_companies.where_values.reduce(:and)
bananas = banana_companies.where_values.reduce(:and)
Company.where(apples.or(bananas))
See ActiveRecord Arel OR condition for more examples.
The best result for this that I've come across is to grab and merge the ids of the two queries and then search for them like this:
apple_companies = Company.where("name like ?","%apple%").pluck(:id)
banana_companies = Company.where("name like ?","%banana%").pluck(:id)
ids = apple_companies + banana_companies.uniq
Company.where(id: ids)
It's four lines that seems like it should be doable in one but it works.
In this case you can use any of the other answers. However in more general cases, I strongly recommend using any_of gem. With this gem you can do:
apple_companies = Company.where("name like ?","%apple%")
banana_companies = Company.where("name like ?","%banana%")
Company.where.any_of(apple_companies, banana_companies)
There already is a pull request to add this functionality to future rails releases.
Please try using
Company.where('name LIKE ? OR name LIKE ?','%apple%', '%banana%')
OR
Company.where('name IN (?)', ['%apple%', '%banana%'])
According to your code:
names = []
company_name_list.each do |name|
names << "%"+name+"%"
end
Then you can do:
companies = Company.where('name LIKE ANY(Array[?])', names)
Late answer, but Arel will solve it.
Company.where(Company.arel_table[:name].matches_any(["%apple%", "%banana%"]))
Use
Company.where(name: IN ('%apple%','%banana%'))

Rails update_all with hstore

What's a good way to update multiple records with hstore columns using activerecord? Right now I'm looping through, updating and saving like this:
time = Time.now.to_s
scoped_tasks.each do |task|
task.data[:last_checked] = time
task.save!
end
Is there any way to do this with an update_all query? One solution I've seen looks like this:
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))
But the problem with that is it overwrites the entire column, so other values are lost. I've also seen this:
MyModel.update_all("data = data || hstore('a', 'blah')")
But for some reason I get back 0 for the value. It also looks like it will only work if the hstore is empty.
I struggled with the same question myself, here is how I was able to solve it:
MyModel.update_all([%(data = data || hstore(?,?)), 'a', 'new_value']))
The core fix for this was wrapping the update_all action in a [] and %(). I am still struggling to figure out how the %() defines the SET in the Postgre SQL so if anyone has an explanation that would be uber-helpful.
In my case I was actually removing a key too (really I wanted to update the key name but keep the value). So if anyone has that issue the code looks like:
MyModel.update_all([%(data = delete("data",?)), 'a'])
I was hoping to do both actions in the same call but that was creating a really odd command in the SQL where the second action was added as part of the WHERE clause not the SET. Still a bit of black magic for me but hopefully this helps...
If you use
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))
then it will cleared out other values and if you try to use
MyModel.update_all("data = data || hstore('a', 'blah')") it will only work if there is any value in hstore column,
so try to use combination of both
if (hstore_column_name).present?
MyModel.update_all("data = data || hstore('a', 'blah')")
else
MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

How to exclude an array of ids from query in Rails (using ActiveRecord)?

I would like to perform an ActiveRecord query that returns all records except those records that have certain ids. The ids I would like excluded are stored in an array. So:
ids_to_exclude = [1,2,3]
array_without_excluded_ids = Item. ???
I'm not sure how to complete the second line.
Background: What I've already tried:
I'm not sure background is necessary, but I've already tried various combinations of .find and .where. For example:
array_without_excluded_ids = Item.find(:all, :conditions => { "id not IN (?)", ids_to_exclude })
array_without_excluded_ids = Item.where( "items.id not IN ?", ids_to_exclude)
These fail. This tip might be on the right track, but I have not succeeded in adapting it. Any help would be greatly appreciated.
Rails 4 solution:
ids_to_exclude = [1,2,3]
array_without_excluded_ids = Item.where.not(id: ids_to_exclude)
This should work:
ids_to_exclude = [1,2,3]
items_table = Arel::Table.new(:items)
array_without_excluded_ids = Item.where(items_table[:id].not_in ids_to_exclude)
And it's fully object-oriented with no strings :-)
You can also use Squeel gem to accomplish such query.
Documentation of it, goes here
As nslocum wrote, the following works well:
Item.where.not(id: ids_to_exclude)
If your "ids to exclude" come from a query (here with an example condition), you can even take it a step further:
Item.where.not(id: Item.where(condition: true))
This is useful if you need to filter another model:
OtherModel.where.not(item_id: Item.where(condition: true))

Resources