Brian Armstrong
Brian Armstrong

Reputation: 19863

Custom queries in Mongoid

Is it possible to pass custom javascript to Mongoid sort of like find_by_sql or update_all in active record?

The particular case I'm thinking of is I would like to inc a field on a bunch of documents matching a criteria.

It looks like this is possible in MongoDB: http://www.mongodb.org/display/DOCS/Updating#Updating-ModifierOperations

db.people.update( { name:"Joe" }, { $inc: { created_at : -1 } } );

But I don't thing Mongoid allows it (it seems to only let you inc one document at a time). And their update_all method I believe only can use $set. Thanks! http://mongoid.org/docs/querying/modification.html

For example, this doesn't work

User.where(:name => "Joe").update_all("{ $inc: { created_at : -1 } }")

Upvotes: 2

Views: 1347

Answers (2)

Simone Carletti
Simone Carletti

Reputation: 176402

Mongoid offers a Model#inc method but it's an instance method, not a class method.

However, by reading the source code of the Model.update_all method it turns out you can easily create your own inc class method.

def update_all(attributes = {})
  klass.collection.update(
    selector,
    { "$set" => attributes },
    Safety.merge_safety_options(:multi => true)
  ).tap do
    Threaded.clear_safety_options!
  end
end

As you can see, Mongoid is passing the query to the underlying mongodb driver. The following method should work

class User
  def self.inc(field, value)
    klass.collection.update(
      selector,
      { "$inc" => { field => value } },
      Safety.merge_safety_options(:multi => true)
    ).tap do
      Threaded.clear_safety_options!
    end
  end
end

Please note I haven't tested it yet.

Upvotes: 1

RameshVel
RameshVel

Reputation: 65877

What about multi flag specifier in update command

As per the mongodb,

db.collection.update( criteria, objNew, upsert, multi )

multi - indicates if all documents matching criteria should be updated rather than just one. Can be useful with the $ operators below.

so set multi flag true in your update command

db.people.update( { name:"Joe" }, { $inc: { created_at : -1 } },false,true );

Upvotes: 1

Related Questions