Mongodb Group Using Ruby Driver

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:

  1. 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)
  2. 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.
  3. (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)

  1. <query>
  2. 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



Leave a reply



Submit