MongoDB Group using Ruby driver
That's pretty strange behavior. I just ran your code locally, and everything worked. Can you verify that you're using the driver version 0.18.2? If so, make sure that that's the only version installed (just as a sanity check).
I don't think it should make any difference, but I wasn't running #group from MongoMapper -- I was using the gem alone. You might try that, too. Here's the code I ran:
require 'rubygems'
require 'mongo'
d = Mongo::Connection.new.db('blog')
c = d['post']
p c.group("function(x) { return { month: x.date.getMonth(), year:x.date.getFullYear() }; }",
nil,
{ :count => 0 },
"function(x,y){y.count++}",
true)
How to use MongoDB Ruby Driver to do a Group (group by)?
I finally got it to work by
Analytic.collection.group( ['myapp_id'], {:page => 'products'},
{:pageviews => 0, :timeOnPage => 0},
"function(x, y) { y.pageviews += x.pageviews; y.timeOnPage += x.timeOnPage }" )
but then I used Map/Reduce afterwards as Map/Reduce seems like a more generic and powerful method.
Mongo Group Query using the Ruby driver
This is how the function finally took shape using the 1.10.0 Mongo gem:
@db.collection("audit_log").group(
[:user, :events],
{'events' => { '$elemMatch' => { 'action' => 'LOGIN_SUCCESS' }}},
{ 'lastLoginTs' => -1, 'loginsCount' => 0 },
"function(current, result){ result.loginsCount++; result.lastLoginTs = Math.max(result.lastLoginTs, current.timeStamp);}",
"function(result){ result.lastLoginDate = new Date(result.lastLoginTs).toISOString().split('T')[0];}"
)
With the Mongo Driver, you leave off the keys: "key", "cond", "initial", "reduce", "finalize" and simply pass in the respective values.
I've linked to two approaches taken by other SO users here and here.
How to create a view using mongo-ruby-driver
To create a view (say management_feedback
) on a collection (say survey
):
client = Mongo::Client.new(['127.0.0.1:27017'], database: 'my-db')
client[
:management_feedback,
viewOn: 'survey',
pipeline: [
{ $project: { "management": "$feedback.management", department: 1 } }
]
].create
Ruby mongo driver: Catch MongoDB connection errors after a few seconds?
You're on the right track. server_selection_timeout
is the correct option in this case -- it tells the driver how long to wait to find a suitable server before timing out. You can set that option on a new client in the Mongoid configuration file (config/mongoid.yml
).
You want your configuration file to look something like this:
development: # (or production or whatever environment you're using)
clients:
default:
# your default client here
new_client: # the name of your new client with different options
database: mongoid
hosts:
- localhost:27017
options:
server_selection_timeout: 6
...
Read the Mongoid Configuration documentation to learn more about setting up config files.
Then, you want to use the new client you defined to perform your query, and rescue any Mongo::Error::NoServerAvailable
errors.
begin
User.with(client: 'new_client').collection.find({}).count()
rescue Mongo::Error::NoServerAvailable => e
# perform error handling here
end
Note that this starts up a new Mongo::Client
instance, which is an expensive operation if done repeatedly. I would recommend that you close the extra client once you are done using it, like so:
Mongoid::Clients.with_name('new_client').close
Grouping by Polygons in MongoDB
When you want to group, you need to use the aggregation framework. You will need an aggregation pipeline with two steps and an optional 3rd step:
- The above query with a $match operator (by the way: the $and is unnecessary. You can put
"geometry.coordinates"
and"properties.time"
in the same associative array) - a $group operator which
_id => "$cityname"
(I guessed cityname is the field where the name of the city is stored) and"number_of_points" => { "$sum" => 1 }
. The new field number_of_points will contain the number of points per city. - (optional) The name of the city will now be in the field _id. When you want the field to have a different name, you can rename it with an additional $project step.
Mongo full text search with score via Ruby driver
Let's look to structure of mongo
command:
db.collection.find(
<query>,
{ score: { $meta: "textScore" } }
)
We see that command contains two parts (in this case find
)
<query>
options hash
Structure of command in mongo-driver very similar to mongo. But some things are not simple.
In mongo-driver we have Mongo::Collection::View
, check (link to source):
articles.find({ '$text': { '$search': 'cake' } }.class # => Mongo::Collection::View
So after analyzing code, i found that you can use projection
option, but it is tricky:
articles.find(
{ "$text" => { "$search" => "cake" } },
projection: {
"score" => { "$meta" => "textScore" },
some_field: 1
})
My test was:
posts.find(
{ "$text" => { "$search" => "house" } },
projection: { "score" => { "$meta" => "textScore" }, rooms: 1 }
)
Results is:
{"_id"=>BSON::ObjectId('53f5c8b54465764a82fb0000'),
"rooms"=>2.0,
"score"=>0.5004448398576512}
Related Topics
Post Redirect Get Pattern in Rails
Accessing a Has_One Associations' Attributes
How to Set Up the Recipient Id in Public Activity
Rails Routing - Custom Routes for Resources
Ssl_Connect Error When Accessing Shopify API with Rubygem
How to Create a Custom Method for the Rails Console
Importing CSV Data into Rails App, Using Something Other Then the Association "Id"
Building Gem, Executable Not Found
Fast-Stemmer Installation Problems
Exec the Cd Command in a Ruby Script
Selenium2 Webdriver Ruby => How Click on a Hidden Link
Requiring a Ruby Gem in Ruby Script Breaks Cron Job Execution
How to Convert PDF to Excel or CSV in Rails 4
How to Ssh Interactive Session