Positional updates for collections?

20 views
Skip to first unread message

Billy

unread,
May 31, 2011, 7:59:36 PM5/31/11
to mongo...@googlegroups.com
Does MongoMapper or any plugin created for it  support the positional operator? I have a 6-level-deep embedded document structure on my primary model and I notice that while I can use .push on my primary model to get things tacked on to the 1st level collections, I can't go beyond that without re-creating the entire collection every time I add.

I am currently assembling a 1.5 meg  document in  memory then saving to mongo in 1 shot. This document doesn't need to be updated at all after the initial write, but I am concerned with this massive write going out. It's taking around 8 seconds to write it all out from MM and I want to switch to just assembling the data in mongo as I progress to avoid locking the table for too long. I was hoping something was written already so I don't have to re-create my collections every time I want to add something to it.

Mongo itself supports something like:  db.as.update( {"_id" : ObjectId("4de579c3c643cf0f60000001")}, {$push: {'bs.N.cs':  {"_id": ObjectId("4de579c3c643cf0f60000099")} }  } )
(http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator)

Where N is the Nth element of the array/collection.

Sample code/console:

class A
  include MongoMapper::Document
  many :bs
end

class B
  include MongoMapper::EmbeddedDocument
  has_one :a
  many :cs
end

class C
  include MongoMapper::EmbeddedDocument
  has_one :b
end

> a = A.new
> a.save

MONGODB development['as'].update({:_id=>BSON::ObjectId('4de579c3c643cf0f60000001')}, {"_id"=>BSON::ObjectId('4de579c3c643cf0f60000001'), "bs"=>[]})

> a.reload

MONGODB development['as'].find({:_id=>BSON::ObjectId('4de579c3c643cf0f60000001')})

> a.push(:bs => B.new.to_mongo)

MONGODB development['as'].update({:_id=>{"$in"=>[BSON::ObjectId('4de579c3c643cf0f60000001')]}}, {"$push"=>{:bs=>{"_id"=>BSON::ObjectId('4de579cdc643cf0f60000002')}}})

> a.reload

MONGODB development['as'].find({:_id=>BSON::ObjectId('4de579c3c643cf0f60000001')})

> a.bs  #  => [#<B _id: BSON::ObjectId('4de5778dc643cf0eda000011')>]
> b  = a.bs.first
> b.cs  #  => []
> b.push(:cs => C.new) # NoMethodError: undefined method `push' for #<B _id: BSON::ObjectId('4de5778dc643cf0eda000011')>
> b.cs << C.new #  => [#<C _id: BSON::ObjectId('4de577b3c643cf0eda000013')>]
> b.save # I only want to save Bs, but its also re-saving A

MONGODB development['as'].update({:_id=>BSON::ObjectId('4de579c3c643cf0f60000001')}, {"_id"=>BSON::ObjectId('4de579c3c643cf0f60000001'), "bs"=>[{"_id"=>BSON::ObjectId('4de579cdc643cf0f60000002'), "cs"=>[{"_id"=>BSON::ObjectId('4de579efc643cf0f60000004')}]}]})







Corresponding Mongo queries:

> db.as.find( {"_id" : ObjectId("4de579c3c643cf0f60000001")} )
{ "_id" : ObjectId("4de579c3c643cf0f60000001"), "bs" : [
        {
                "_id" : ObjectId("4de579cdc643cf0f60000002"),
                "cs" : [
                        {
                                "_id" : ObjectId("4de579efc643cf0f60000004")
                        }
                ]
        }
] }

> db.as.update( {"_id" : ObjectId("4de579c3c643cf0f60000001")}, {$push: {'bs.0.cs':  {"_id": ObjectId("4de579c3c643cf0f60000099")} }  } )

> db.as.find( {"_id" : ObjectId("4de579c3c643cf0f60000001")} )                                                                           

{ "_id" : ObjectId("4de579c3c643cf0f60000001"), "bs" : [
        {
                "_id" : ObjectId("4de579cdc643cf0f60000002"),
                "cs" : [
                        {
                                "_id" : ObjectId("4de579efc643cf0f60000004")
                        },
                        {
                                "_id" : ObjectId("4de579c3c643cf0f60000099")
                        }
                ]
        }
] }

Shem Magnezi

unread,
Dec 26, 2013, 7:54:16 AM12/26/13
to mongo...@googlegroups.com
Just do something like this:
A.push( {:_id => ObjectId("4de579c3c643cf0f60000001")}, {'bs.0.cs' =>  {"_id": ObjectId("4de579c3c643cf0f60000099")} }  )
Reply all
Reply to author
Forward
0 new messages