An more elegant way to query MongoDB in Ruby? - ruby

I am fairly new to Ruby and MongoDB in particular. I use Mongo in a Ruby script to store and process thousands of Tweets in a collection. I would love to improve legibility and "rubyness" of the find command here:
require 'rubygems'
require 'mongo'
db = Mongo::Connection.new("localhost").db("db")
coll = db.collection("tweets")
cursor = coll.find({
'geo_enabled' => true,
'status.text' => { '$exists' => true },
'followers_count' => {
'$gte' => 10,
'$lt' => 100 }
})
cursor.each_with_index { |row,idx|
# do stuff
}
The mongodb query syntax drives me nuts! Is there a more elegant, ruby-like way to do a query?

You can use Mongoid, it has nice syntax for queries, much similar to that of ActiveRecord/ActiveRelation.

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 Mongo gem bulk insert of enumerable

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

Rails 3.1 urllib2.quote(json.dumps(var)) Equivalent

In Python I can convert JSON into a useable encoded string eg:
cmd2 = [{'cmd': 'inlinepush',
'params': {'raw': 'score'
}
}]
url = urllib2.quote(json.dumps(cmd2))
print url
This produces:
%5B%7B%22cmd%22%3A%20%22inlinepush%22%2C%20%22params%22%3A%20%7B%22raw%22%3A%20%22score%22%7D%7D%5D
I have searched and searched but not found a Ruby or Rails equivalent, particularly in the NET::HTTP library.
I really have spent a lot of time thrashing to no end and would be grateful of any pointers.
Try this:
require 'cgi'
require 'json'
cmd2 = [{
'cmd' => 'inlinepush',
'params' => {
'raw' => 'score'
}
}]
puts CGI.escape(JSON.dump(cmd2))

Does :include inside a sunspot/solr searchable method do anything?

I benchmarked 2 version of my solr index the first with the following include statement:
searchable(:auto_index => false, :auto_remove => true,
:include => { :account => true,
:user_practice_contact => [:city],
:user_professional_detail => [:specialty, :subspecialties]}) do
The second:
searchable(:auto_index => false, :auto_remove => true) do
I was expecting to see a speed bump on the version with includes but here is the outcome:
version with includes:
Benchmark.measure { User.limit(50).each do |u|; u.index; end; Sunspot.commit; }
=> #<Benchmark::Tms:0x1130b34e8 #real=6.8079788684845, #utime=5.05, #cstime=0.0, #cutime=0.0, #total=5.2, #label="", #stime=0.149999999999999>
and without the includes:
Benchmark.measure { User.limit(50).each do |u|; u.index; end; Sunspot.commit; }
=> #<Benchmark::Tms:0x112ef0fe8 #real=6.82465195655823, #utime=4.92, #cstime=0.0, #cutime=0.0, #total=5.07, #label="", #stime=0.15>
Does anybody know if the includes are supposed to work? And if so, am I doing it wrong?
I looked at the docs: http://outoftime.github.com/sunspot/rails/docs/ and see no mention of that.
According to the API, :include will:
allow ActiveRecord to load required associations when indexing.
Your benchmark does not work properly because you are indexing individual records in an ordinary Ruby iterator. As you are indexing a single record 50 times, Sunspot wouldn't be able to utilize the eager loading at all. Instead you should do:
Sunspot.index( User.limit(50) );
Sunspot.commit
Oh and could you test if the following is faster than above? I really want to know.
Sunspot.index( User.includes(:account).limit(50) );
Sunspot.commit
Also there is a bug currently that STI models will ignore the :include.
By looking at the SQL queries in the Rails log, you can see that :include on searchable causes eager loading while indexing. :include on #search caused eager loading while searching.

Resources