Rails update_all with hstore - ruby

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}))

Related

Where clause not working. Laravel

I'm trying to count result from my query which is using multiple where query. But it doesn't seem to be working.
My syntax is:
$partialpaidquery=['month' => $maina];
$partialpaid=Bill::where($partialpaidquery)->where('paid','!=',0)->where('fee_status','<','amount')->count();
where clause upto where('paid','!=',0) seems to work but the third one is not working. What is the problem here? It actually should have returned 1. But it is returning 0.
Seems you are using wrong query :
You are comparing < string 'amount' instead of use variable $amount
like below:
$partialpaidquery=['month' => $maina];
$partialpaid=Bill::where($partialpaidquery)->where('paid','!=',0)->where('fee_status','<',$amount)->count();
Use your third where as
->whereRaw('fee_status < amount')
because the way you are using it , the amount column is being interpreted as string not column.

Finding Last Name Using LINQ

I am trying to get last name using linq in visual studio. In my database, i have the Field name like "FullName".
In this Field I have value like "Subbu Cargos"
I Wanna Display the "Cargos" in my textbox.
How can i make a simple linq query?
Would it be over simple to say:
return FullName.Split(' ').Last()
?
I would suggest breaking it up into different fields - Firstname, Middlename, lastname, Title - and rebuilding the name on the fly when you come to display it.
If you're still determined to use one field, then consider a query like:
string s = "Subba Cargos";
var lastnames = from name in s.Split(new Char[] { ' ' }).Last<string>()
select name;
I would suggest not trying to parse out the last name. Like you say, first and last names could be switched around, someone might have a second name, or a last name that consists of multiple words (“van Dijk”), or may not have entered a last name at all.
Check out this article: Falsehoods Programmers Believe About Names
If you still want to do this however, try something like this:
customers.Select(c => c.FullName.Split(' ').Last());
You might not be able to this on the server side. In that case:
customers
.Select(c => c.FullName)
.ToList()
.Select(n => n.Split(' ').Last());
Untested, but this should give a rough idea.
You could also do it like this:
customers
.Select (b => b.FullName.Substring ((b.FullName.IndexOf(' ') + 1)));

EntityFramework Linq query

I cannot understand what is wrong with following query:
var tmp = dbset.AsEnumerable<mytable>().Where(
c=>c.Barcode.Contains("11") && c.Description.Contains("EW") );
return tmp;
Should this be same as:
select * from mytable
where Barcode like '%11%' and Description like '%EW%';
If I run this in sql server i get four rows as it should be, but not when I run the linq query
i get 0 rows.
Can please someone help me. It is rather a simple query and it is giving me such a headache. Thank you very much
You forget fetch data, do this:
var tmp = dbset.AsEnumerable<mytable>().Where(
c=>c.Barcode.Contains("11") && c.Description.Contains("EW") );
return tmp.ToList();
Also do not call AsEnumerable soon, use it as below:
var tmp = ctx.mytable.Where(
c=>c.Barcode.Contains("11") && c.Description.Contains("EW") );
return tmp.ToList();
dbset.AsEnumerable<mytable>()...
Don't do that!
You are causing all your data to get pulled from the database before checking the Where condition.
Other than that, it's not really clear why your query isn't working. Your syntax is correct. I'm guessing the data doesn't actually look like you think it does. Either that, or you're expecting like %EW% to match something in a case-insensitive manner and since the Where clause is being evaluated by LINQ to Objects you're not getting that behavior.
Run a query with only one condition? " c.Barcode.Contains("11") ".
That code should run fine.

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))

How can I retrieve a document by _id?

I'm trying to retrieve a document when I have an object id - however, the query does not work.
#collection = #db.collection('Mylist')
#result = #collection.find({"_id" => params[:id]})
I've tried variations of the query - it always yields empty - however when I try a query on the collection such as below, that would work.
#result = #collection.find({"Exist" => "True"})
Why? It is strange that complex queries work but a simple query by _id returns nothing.
If possible, I don't want to use MongoMapper.
Thanks
Found it - you need to wrap it like this -
find({"_id" => Mongo::ObjectId(params[:id])})
find(:_id => BSON::ObjectID(params[:id])
This would also work:
#coll.find_one(ObjectID.from_string(params[:id]))

Resources