11
votes

Lets take a simple "bad" example : lets assume I have 2 collections 'person' and 'address'. And lets assume in 'address' I want to store '_id' of the person the address is associated with. Is there any benefit to store this "referential key" item as ObjectId vs string in 'address' collection?

I feel like storing them as string should not hurt but I have not worked in mongo for very long and do not know if it will hurt down the road if I follow this pattern.

I read the post here : Store _Id as object or string in MongoDB? And its said that ObjectId is faster, and I assume its true if you are fetching/updating using the ObjectId in parent collection(for eg. fetching/updating 'person' collection using person._id as ObjectId), but I couldn't find anything that suggests that same could be true if searching by string id representation in other collection(in our example search in address collection by person._id as string)

Your feedback is much appreciated.

3
How is this a different question? An ObjectId is stored in 12-bytes. A string with the hexadecimal charcters of an ObjectId is 24-bytes ( just for characters, the plus trailing then plus size reference). More space, more time. Slower! That should not be difficult to work out.Blakes Seven
You are right, was trying to work things out with ember data and didnt see much point in converting objectid to string and back to objectId and i was searching for convenience more than performance. This morning i did a search and this question has been asked in other form too.Deewendra Shrestha
For the record the answer you accepted here makes the other important point. You cannot match things together on different "types" without manually re-casting to either string or ObjectId values. Personally I really prefer all external API to use the extended JSON form { "_id": { "$oid": "56ea9e8bb1e015d13b376db5" } } since if my client can actually deserialize back to an ObjectId then I let it know that is what the data actually is.Blakes Seven

3 Answers

10
votes

Regardless of performance, you should store the "referential key" in the same format as the _id field that you are referring too. That means that if your referred document is:

{ _id: ObjectID("68746287..."), value: 'foo' }

then you'd refer to it as:

{ _id: ObjectID(…parent document id…), subDoc: ObjectID("68746287...")

If the document that you're pointing to has a string as an ID, then it'd look like:

{ _id: "derick-address-1", value: 'foo' }

then you'd refer to it as:

{ _id: ObjectID(…parent document id…), subDoc: "derick-address-1" }

Besides that, because you're talking about persons and addresses, it might make more sense to not have them in two documents altogether, but instead embed the document:

{ _id: ObjectID(…parent document id…),
  'name' : 'Derick',
  'addresses' : [
     { 'type' : 'Home', 'street' : 'Victoria Road' },
     { 'type' : 'Work', 'street' : 'King William Street' },
  ]
}
3
votes

As for use string as id of document, in meteor collection, you could generate the document id either Random.id() as string or Meteor.Collection.ObjectID() as ObjectId.

In this discussion loop, Mongodb string id vs ObjectId, here is one good summary,

ObjectId Pros

  • it has an embedded timestamp in it.
  • it's the default Mongo _id type; ubiquitous
  • interoperability with other apps and drivers

ObjectId Cons

  • it's an object, and a little more difficult to manipulate in practice.
  • there will be times when you forget to wrap your string in new ObjectId()
  • it requires server side object creation to maintain _id uniqueness - which makes generating them client-side by minimongo problematic

String Pros

  • developers can create domain specific _id topologies

String Cons

  • developer has to ensure uniqueness of _ids
  • findAndModify() and getNextSequence() queries may be invalidated

All those information above is based on the meteor framework. For Mongodb, it is better to use ObjectId, reasons are in the question linked in your question.

1
votes

Storing it as objectId is benificial. It is faster as ObjectId size is 12 bytes compared to string which takes 24 bytes.

Also, You should try to de-normalize your collections so that you don't need to make 2 collections (Opposite to RDBMS).

Something like this might be better in general:

{ _id : "1",
  person : { 
             Name : "abc",
             age: 20
           },
  address : { 
             street : "1st main",
             city: "Bangalore",
             country: "India"
            }
}

But again, it depends on your use case. This might be not suitable sometimes.

Hope that helps! :)