Ruby Mongo gem bulk insert of enumerable - ruby

I am using ruby 1.9.3 with the twitter and mongo gems.
I have the following code working:
Twitter.user_timeline("GSElevator", :count => 200, :exclude_replies => "true", :include_rts => "false").each do |r| rawtest.insert(r.attrs) end
My currently method of looping through each enumerable and then inserting the attrs, one by one, proves to be relatively slow.
How can I insert the 200 enumerables in a single, quick batch?
Thanks in advance for the help.

You can pass an array of documents to the insert method:
rawtest.insert(Twitter.user_timeline("GSElevator", params).map(&:attrs))

Related

Get RethinkDB query working in Ruby on Rails

I have a ReQL query...
r.db('development').table('responses').filter({
survey_id: 9
}).concatMap(r.row.getField('numerical_answers')).filter({
type: 'CustomerEffortAnswer'
}).sum('number')
...that I would like to get working in NoBrainer because I can't seem to get it working on Ruby on Rails. When I try to run just the ReQL in Rails like so...
NoBrainer.run do |r|
return_count = r.db('development').table('responses').filter({ survey_id: id }).concatMap(r.row.getField('numerical_answers')).filter({type: 'CustomerEffortAnswer'}).sum('number')
end
...I get the error:
Sorry, r.row is not available in the ruby driver. Use blocks instead.
Needed to convert the code over to Ruby language:
return_count = NoBrainer.run do |r|
r.db('development').table('responses')
.filter({:survey_id => 9})
.concat_map { |doc| doc[:numerical_answers] }
.filter({:type => 'CustomerEffortAnswer'})
.sum('number')
end

How can I find entries that match a certain array of values with the mongo ruby driver

I know I can find entries in mongodb that match a certain array of values natively via this command:
db.vendors.find({"somearray.property": { $in: ["value1","value2"]}})
But how can I do this with the ruby driver 'mongo' gem?
col.find("somearray.property" => ["value1","value2"])
Regards
You can do it like this:
col.find("somearray.property" => { '$in' => ["value1","value2"] })
Not sure to understand what you mean by the "ruby driver" but if you are using mongoid (which I recommend when dealing with mongodb) you can do
col.where(:'somearray.property'.in => ["val1", "val2"])
More informations here

Ruby: How to get array instead of DataMapper::Collection in query result

here is my code:
today_ids_from_db = Rating.all(:fields => 'my_id', :ts_d => Time.now)
today_ids_from_db.class == DataMapper::Collection
but I need to get simple ruby array with my_id values
how to achieve this?
You can also try out this Activerecord beauty called pluck
Rating.where(:ts_d => Time.now).pluck(:my_id)
Try this code
Rating.all(:ts_d => Time.now).map(&:my_id)

PG gem returning columns in random order

Is it normal for the latest version of the 'pg' gem to return the results of a db query columns in a random order? I would expect that the 'pg' gem would behave in the same manner as the mysql2 gem, returning the data in the order it is presented when querying the database directly via the command line. Maybe there is a better gem out there that I should be using. This example of my results below are a result of useing the same query, "select * from books"
First execution:
"The Shining","9","7808","4156"
"Dune","15","4513","1866"
"2001: A Space Odyssey","15","4267","2001"
"The Cat in the Hat","2","1608","1809"
"Bartholomew and the Oobleck","2","1590","1809"
Second execution:
"4156","The Shining","9","7808"
"1866","Dune","15","4513"
"2001","2001: A Space Odyssey","15","4267"
"1809","The Cat in the Hat","2","1608"
"1809","Bartholomew and the Oobleck","2","1590"
Third execution:
"9","The Shining","7808","4156"
"15","Dune","4513","1866"
"15","2001: A Space Odyssey","4267","2001"
"2","The Cat in the Hat","1608","1809"
"2","Bartholomew and the Oobleck","1590","1809"
Code to return results:
confrom = PG::Connection.new(:user => <myuser>, :password => <mypw>, :port => 5432, :host => <myhost>, :dbname => 'booktown')
results = confrom.exec("select * from books")
results.each do |row|
row.each_value do |x|
puts x
end
end
I'm guessing that you're using Ruby 1.8.X where Hashes don't have any defined order. I tried similar code with pg and Ruby 1.9.3 and everything came out in the same order each time.
In here:
results.each do |row|
#...
end
the row will be a simple Hash. So when you row.each_value, you can't depend on your x values coming out in any particular order in Ruby 1.8; in 1.9 you should get your x values in insertion order.
But all of that really doesn't matter anyway:
You should avoid select * ... except when you're manually poking around inside the database; you should always say select c1, c2, ... so that you know exactly what you're getting from the database and what order everything will come out in. If someone adds a column or if a column changes position, then all your code will break.
You have a Hash in row so you can access the results by name and this is easier and less error prone than mucking about with positions.

Exact opposite to Ruby's CGI.parse method?

I'd like to do some sanitization of query params.
I parse the query with CGI.parse, then I delete some params, but I can't find an opposite method to build the query.
I don't really want to do something like
params.map{|n,v| "#{CGI.escape n}=#{CGI.escape v.to_s}"}.join("&")
There's got to be a simpler way. Is there?
There is a nice method in URI module:
require 'uri'
URI.encode_www_form("q" => "ruby", "lang" => "en") #=> "q=ruby&lang=en"
If you're using Rails (or don't mind pulling in ActiveSupport), then you can use to_param (AKA to_query):
{ :a => '&', :b => 'Where is pancake house?', :c => ['an', 'array'] }.to_param
# a=%26&b=Where+is+pancake+house%3F&c%5B%5D=an&c%5B%5D=array
to_param handles arrays a little differently than your version though, it'll put out c[]=an&c[]=array rather than just c=an&c=array.
While there's no better answer, I'll put up the method which I'm using now.
def build_query(params)
params.map do |name,values|
values.map do |value|
"#{CGI.escape name}=#{CGI.escape value}"
end
end.flatten.join("&")
end
I am not sure if the following is a simplification, but it avoids expanding the (key, value) pairs of a hash.
params.map{|qq| qq.map{|q| CGI.escape(q)}.join('=')}.join('&')

Resources