简体   繁体   中英

mongoid create 2 embedded document with the same mongo “_id”

Does it make sense that I have a mongodb record which one of its field is an array of two identical embedded documents (even the "_id" is identical).

I encounter this problem when I use mongoid to create records. I don't know much about mongoid's embedded documents implementation, but I guess if those embedded documents are "documents", none of them should have an "_id" that is already in use by another doc.

An example of what I got:

{
   _id: "123",
   name: "sylvain",
   friends: [ ]
},
{
   _id: "245",
   name: "sonia",
   friends: [ {
      _id: 123,
      name: "sylvain"
   },
   {
      _id: 123,
      name: "sylvain"
   } ]
},
{
   _id: "456",
   name: "bob",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
}

In order to make things clear:

  • The _id field is mandatory on each root document of a collection. It is used to uniquely identify your document. Think of it as the primary key on your collection. There is always an index on that _id field.
  • Typically , there is no unique identifier for embedded documents (they simply don't need that: embedded documents are really part of their parent document -- this not a view on two "joined" collections).
  • But , you can add an id field in embedded documents as a foreign key for example. Even if this could be rather confusing, you might even call it _id if you want. However it will not have any special meaning in that context.

As NoSQL databases tend to use denormalized schema, it is quite common in MongoDB to have identical documents embedded in different root documents. In fact, this is one way to represent a many-to-many relationship.


Here is a perfectly valid example (even if, as I said before, the use of _id as a field name might be confusing at first sight):

{
   _id: "123",
   name: "sylvain",
   friends: [ ]
},
{
   _id: "245",
   name: "sonia",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
},
{
   _id: "456",
   name: "bob",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
}


As about having two identical documents embedded in the same parent document: this might be a way to "count" the number of references from the parent to the child. Think of you parent-child document relation as a graph. You might very well have two links from one node to the other -- On the other hand, one would think of adding some "weight" field to the embedded document instead (so, qualifying the link ). Depending your use case, both solutions might have pros and cons.

Here is an example using two different models representing the following facts:

"The customer sylvain currently hold two coupons for a free MP3 download on our store"

// customer
{
   _id: "123",
   name: "sylvain",
   coupons: [ {
        _id: 9905,
        desc: "Free MP3 download"
   },
   {
        _id: 9905,
        desc: "Free MP3 download"
   } ]
}

Alternatively, one might think of it more that way:

// customer
{
   _id: "123",
   name: "sylvain",
   coupons: [ {
        _id: 9905,
        desc: "Free MP3 download",
        qty: 2
   } ]
}

As of myself, I think it is not that obvious if that latter is really better than the former one. For example, in the latter case, when the customer uses a coupon, you will have to decrease the qty -- and remove the coupon if qty == 0 . Seems to be more work than in the former case. But YMMV.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM