2

I have a collection of documents in MongoDB that has an attribute being stored as a string when it would work better if it was saved as BSON::ObjectId.

The collection name is foo and the field is called bar. What's the best way to have every field bar turn its existing value into an instance of BSON::ObjectId?

randombits
  • 47,058
  • 76
  • 251
  • 433

2 Answers2

6

Is this what you mean? (You have a string that is the hex of an ObjectId, and you want to turn it into an ObjectId)

> db.foo.insert({bar:new ObjectId().str});
> db.foo.insert({bar:new ObjectId().str});
> db.foo.insert({bar:new ObjectId().str});
> db.foo.find();
{ "_id" : ObjectId("4f95e00d9060633ce7fbab94"), "bar" : "4f95e00d9060633ce7fbab93" }
{ "_id" : ObjectId("4f95e0119060633ce7fbab96"), "bar" : "4f95e0119060633ce7fbab95" }
{ "_id" : ObjectId("4f95e0119060633ce7fbab98"), "bar" : "4f95e0119060633ce7fbab97" }
> db.foo.find().forEach(function(doc) { db.foo.update({_id:doc._id},{$set:{bar:new ObjectId(doc.bar)}}); });
> db.foo.find();
{ "_id" : ObjectId("4f95e00d9060633ce7fbab94"), "bar" : ObjectId("4f95e00d9060633ce7fbab93") }
{ "_id" : ObjectId("4f95e0119060633ce7fbab96"), "bar" : ObjectId("4f95e0119060633ce7fbab95") }
{ "_id" : ObjectId("4f95e0119060633ce7fbab98"), "bar" : ObjectId("4f95e0119060633ce7fbab97") }

Or is this what you mean? (You have a string but you want to blow it away and create a new ObjectId in its place)

> db.foo.insert({bar:"some string id"});
> db.foo.insert({bar:"some string id2"});
> db.foo.insert({bar:"some string id3"});
> db.foo.find();
{ "_id" : ObjectId("4f95e1779060633ce7fbaba5"), "bar" : "some string id" }
{ "_id" : ObjectId("4f95e1799060633ce7fbaba6"), "bar" : "some string id2" }
{ "_id" : ObjectId("4f95e17b9060633ce7fbaba7"), "bar" : "some string id3" }
> db.foo.find().forEach(function(doc) { db.foo.update({_id:doc._id},{$set:{bar:new ObjectId()}}); });
> db.foo.find();
{ "_id" : ObjectId("4f95e1779060633ce7fbaba5"), "bar" : ObjectId("4f95e1819060633ce7fbaba8") }
{ "_id" : ObjectId("4f95e1799060633ce7fbaba6"), "bar" : ObjectId("4f95e1819060633ce7fbaba9") }
{ "_id" : ObjectId("4f95e17b9060633ce7fbaba7"), "bar" : ObjectId("4f95e1819060633ce7fbabaa") }
Eve Freeman
  • 32,467
  • 4
  • 86
  • 101
  • Can you clarify for future readers what the difference is between these two approaches and why the OP might choose it? Just a random choice between two answers isn't incredibly helpful out of context. :) – Jimmy Sawczuk Apr 23 '12 at 23:14
  • 1
    Done. I was partly hoping he would clarify so I could delete one of my answers, but I guess it might be useful to have both. – Eve Freeman Apr 23 '12 at 23:20
  • 1
    Hi Wes. My objects are already a hex representation in string format. I just need to update the existing strings into instances of ObjectId. An in place update would be best without having to reinsert all of the documents and deleting the old ones. – randombits Apr 23 '12 at 23:55
  • Yeah, that's what my first script does: `db.foo.find().forEach(function(doc) { db.foo.update({_id:doc._id},{$set:{bar:new ObjectId(doc.bar)}}); });` – Eve Freeman Apr 24 '12 at 00:08
  • Note that if your "bar" attribute happens to be "_id" (as in my case), you can't do that, i.e., you can't update _id in MongoDB - see [here](http://stackoverflow.com/a/4012997/297313). – guidoman Nov 05 '14 at 14:12
1

I don't think you can change an objects ID, but you can do something like this:

db.whatevers.find().forEach(function(x) {
   x.oldId = x._id; // this can be handy :)
   x._id = new ObjectID();
   db.whatevers.insert(x);
})

db.whatevers.remove({oldId:{$exists:false}}};
Jamund Ferguson
  • 16,721
  • 3
  • 42
  • 50