14

Is this example of nesting generally accepted as good or bad practice (and why)?

A collection called users:

user
    basic
        name : value
        url : value
    contact
        email
            primary : value
            secondary : value
        address
            en-gb
                address : value
                city : value
                state : value
                postalcode : value
                country : value
            es
                address : value
                city : value
                state : value
                postalcode : value
                country : value

Edit: From the answers in this post I've updated the schema applying the following rules (the data is slightly different from above):

  • Nest, but only one level deep
  • Remove unneccesary keys
  • Make use of arrays to make objects more flexible

    {
       "_id": ObjectId("4d67965255541fa164000001"),
       "name": {
         "0": {
           "name": "Joe Bloggs",
           "il8n": "en" 
          } 
        },
       "type": "musician",
       "url": {
         "0": {
           "name": "joebloggs",
           "il8n": "en" 
          } 
        },
       "tags": {
         "0": {
           "name": "guitar",
           "points": 3,
           "il8n": "en" 
          } 
        },
       "email": {
         "0": {
           "address": "joe.bloggs@example.com",
           "name": "default",
           "primary": 1,
           "il8n": "en" 
          } 
        },
       "updates": {
         "0": {
           "type": "news",
           "il8n": "en" 
          } 
        },
       "address": {
         "0": {
           "address": "1 Some street",
           "city": "Somecity",
           "state": "Somestate",
           "postalcode": "SOM STR",
           "country": "UK",
           "lat": 49.4257641,
           "lng": -0.0698241,
           "primary": 1,
           "il8n": "en" 
          } 
        },
       "phone": {
         "0": {
           "number": "+44 (0)123 4567 890",
           "name": "Home",
           "primary": 1,
           "il8n": "en" 
          },
         "1": {
           "number": "+44 (0)098 7654 321",
           "name": "Mobile",
           "il8n": "en" 
          } 
        } 
    }
    

Thanks!

Community
  • 1
  • 1

4 Answers4

14

In my opinion above schema not 'generally accepted', but looks like great. But i suggest some improvements thats will help you to query on your document in future:

User
    Name 
    Url
    Emails {email, emailType(primary, secondary)}
    Addresses{address, city, state, postalcode, country, language}

Nesting is always good, but two or three level nesting deep can create additional troubles in quering/updating.

Hope my suggestions will help you make right choice of schema design.

Andrew Orsich
  • 52,935
  • 16
  • 139
  • 134
  • 1
    +1, this removes some artificial restrictions of the original schema, like not letting a user have multiple addresses in the same country. – Tobu Feb 24 '11 at 21:37
  • 1
    Thanks for this, defiantely makes sense. Why would nesting deep cause problems querying/updating though? –  Feb 25 '11 at 10:47
  • 1
    Main problems in updating, for example you can't update two deep nestead arrays in position by condition. – Andrew Orsich Feb 25 '11 at 10:56
  • Also just to clarify - you're suggesting emails and addresses should be an array of objects? –  Feb 25 '11 at 11:00
  • @Colin: Yes, you are right. Because if in future you will need 'new' type of email or address you just add it to collection. – Andrew Orsich Feb 25 '11 at 11:16
  • Yes that makes it much more flexible. I've just posted below a new example taking these suggestions on board. Thanks. –  Feb 25 '11 at 12:07
  • @Colin: Great schema! In my current project i have almost the same ;) – Andrew Orsich Feb 25 '11 at 12:14
10

You may want to take a look at schema design in MongoDB, and specifically the advice on embedding vs. references.

Embedding is preferred as "Data is then colocated on disk; client-server turnarounds to the database are eliminated". If the parent object is in RAM, then access to the nested objects will always be fast.

user6039980
  • 3,108
  • 8
  • 31
  • 57
Pero P.
  • 25,813
  • 9
  • 61
  • 85
  • Updated link to MongoDB data model design docs: https://docs.mongodb.com/manual/core/data-model-design/ – teuber789 Sep 02 '21 at 14:29
7

In my experience, I've never found any "best practices" for what a MongoDB record actually looks like. The question to really answer is, "Does this MongoDB schema allow me to do what I need to do?"

For example, if you had a list of addresses and needed to update one of them, it'd be a pain since you'd need to iterate through all of them or know which position a particular address was located. You're safe from that since there is a key-value for each address.

However, I'd say nix the basic and contact keys. What do these really give you? If you index name, it'd be basic.name rather than just name. AFAIK, there are some performance impacts to long vs. short key names.

Keep it simple enough to do what you need to do. Try something out and iterate on it...you won't get it right the first time, but the nice thing about mongo is that it's relatively easy to rework your schema as you go.

brianz
  • 7,268
  • 4
  • 37
  • 44
  • True, I guess there's no real need for basic/contact keys - apart from to keep things tidy. –  Feb 25 '11 at 10:48
2

That is acceptable practice. There are some problems with nesting an array inside of an array. See SERVER-831 for one example. However, you don't seem to be using arrays in your collection at all.

Conversely, if you were to break this up into multiple collections, you would have to deal with a lack of transactions and the resulting race conditions in your data access code.

Justin Dearing
  • 14,270
  • 22
  • 88
  • 161