Is it possible to assign ObjectId () to subcollections in MongoDB?

0

Imagine the following collection:

{
    _id:ObjectId("123456..."),
    user:"João",
    artigos:[
        {
            id: new ObjectId(),
            titulo:"Lorem ispsum.",
            texto:"Lorem ipsum dolor sit amet..."
        }
    ]
}

In short: A user can have n articles, which in turn need some form of identification to be found in a query.

Although apparently MongoDB does not accept ObjectId() in subcollections, I tried to generate it this way and it throws an error stating that the parse of the JSON file could not be made. So my question is:

Can I add ObjectId() to subcollections? If not, how would I be able to assign ids to my items within this subcollection?

    
asked by anonymous 26.05.2014 / 19:09

2 answers

1

Can you add ObjectId() to subcollections (or rather subdocuments)?

Yes, but this is not very recommended because considering that the data architecture decision was to put the data as a subdocument, it is assumed that the only important key is that of the parent document.

Of course there are exceptions. If for example we are talking about a person who has n addresses, and we just want to update one of them, and this is a recurring operation. It makes sense to have.

I'm assuming for the example that the Schema statement looks something like this:

Pessoa: {
    enderecos: [
        { _id: ObjectId(), nome: '' },
        ...
    ]
}

I ran a test with your example and it worked as follows:

db.pessoas.insert({
    "_id": ObjectId(),
    "user": "João",
    "artigos": [
        {
            "_id": ObjectId(),
            "titulo": "Lorem ispsum.",
            "texto": "Lorem ipsum dolor sit amet..."
        }
    ]
})
    
26.05.2014 / 20:20
0

This is a matter of document design. Roughly, there are two routes to follow:

  • Include the subdocument ( artigo ) within the root document ( usuario )
  • link / reference secondary document ( artigo ) in primary ( usuario )
  • As you seem to need an identifier for each article, I would first suggest trying to find a natural identifier, such as a single existing archival number. If this is not possible, you can generate any unique identifier at the time of saving the article for the first time, type a UUID / GUID or some string derived from the title and possibly publication date (eg id_artigo: "2014_08_03_lorem_imsum" ).

    If you prefer a sequential number for these articles, a simple way to do this is by creating a sequencias auxiliary collection that you can use to generate those numbers. I use this technique a lot with findAndModify() :

    var contador = db.sequencias.findAndModify({
        query: {'_id': 'artigos'},
        fields: {'_id': 0, 'seq': 1},
        update: {'$inc': {'seq': 1}},
        new: true,
        upsert: true
    });
    var novo_num = contador.seq;
    

    The 1 alternative applies well when articles have only one author / user because you will not duplicate anything:

    {
        _id: ObjectId("123456..."),
        user: "João",
        artigos:[
            {
                id_artigo: "2014_08_03_lorem_impsum",
                data: new Date(2014, 07, 03), 
                titulo: "Lorem ispsum.",
                texto: "Lorem ipsum dolor sit amet..."
            },
            {
                id_artigo: "2013_12_01_so_um_teste",
                data: new Date(2013, 11, 01), 
                titulo: "Só um Teste",
                texto: "Meu primeiro artigo..."
            }
    
        ]
    }
    

    Alternatively 2 can be used when there is a possibility that the same article can be related to more than one author / user, avoiding too much duplication of data:

    Articles :

        {
            _id: "2014_08_03_lorem_impsum",
            data: new Date(2014, 07, 03), 
            titulo: "Lorem ispsum.",
            texto: "Lorem ipsum dolor sit amet..."
        }
    
        {
            _id: "2013_12_01_so_um_teste",
            data: new Date(2013, 11, 01), 
            titulo: "Só um Teste",
            texto: "Meu primeiro artigo..."
        }
    

    Users :

    {
        _id: ObjectId("123456..."),
        user: "João",
        artigos: ["2013_12_01_so_um_teste", "2014_08_03_lorem_impsum"]
    }
    
    {
        _id: ObjectId("987654..."),
        user: "Armando",
        artigos: ["2014_08_03_lorem_impsum"]
    } 
    
        
    03.08.2014 / 20:56