0

I have the following case: A user can add contacts (who are other users) on the website. Optionally, a user may also organize his contacts in groups. A user can have many emails, addresses and phone numbers.

I thought of the following schema design (document store/mongodb). Are there any ways to improve this? My main concern is that the profile picture is embedded inside the document. I know that this is not a good practice, but for this particular purpose (assignment), I have to embed the picture (blob/gridfs) here as well. But I'm wondering how this schema can be improved.

Community
  • 1
  • 1
Moody
  • 851
  • 2
  • 9
  • 23
  • How are you going to use the document? What sort of queries will you run? What sort of updates? – wdberkeley Mar 18 '15 at 19:42
  • Thanks for your comment! I want to query the contacts of a particular user (get all the contacts from a user) and also show these contacts by groups (e.g. grab all the contacts that are in the group family). A user can update his own information and create his own groups (to later add contacts inside of it). – Moody Mar 19 '15 at 08:47

1 Answers1

0

For users, I think your current schema is fine. Keeping multiple addresses, phone numbers, and email addresses in arrays is good because there shouldn't be too many of them for a particular person and it's easy to query for "who has this email address" or "give me all the phone numbers of this person". You do seem to have a redundant e-mail field though - is that a special email, like the address for the account, that's distinguished from a contact email? If so I'd give it a descriptive name for the sake of other maintainers, a name like account_email. I wouldn't keep the photo as a blob, but you said that is some other requirement so I won't critique it.

I like the idea of doing contacts with groups using a separate contacts collection. I'd have a contacts collection with each document representing one contact

{
    "_id" : ObjectId("..."),
    "owner_id" : ObjectId("..."), // reference to user document of contact owner
    "contact_id" : ObjectId("..."), // reference to user document of contact
    "group" : "Rivals" // group name
}

Index on { "owner_id" : 1, "contact_id" : 1 } and maybe { "owner_id" : 1, "group" : 1 } and then queries like the following will be quick:

// get all contacts for user x
db.contacts.find({ "owner_id" : x })
// is user y a contact of user x?
db.contacts.count({ "owner_id" : x, "contact_id" : y }) != 0
// get all contacts in group "family" for user x
db.contacts.find({ "owner_id" : x, "group" : "family" })

Once you retrieve contacts, in order to retrieve human-friendly display information you will need to do a second query (application-level join) to retrieve the actual user documents of the contacts. If you want, you can denormalize some of the contact info into the contact document

{
    "_id" : ObjectId("..."),
    "owner_id" : ObjectId("..."), // reference to user document of contact owner
    "contact_id" : ObjectId("..."), // reference to user document of contact
    "group" : "Rivals", // group name
    "contact_name" : "Franke Frankers"
}

You won't need to do a second query if you include commonly needed info, but if the contact updates his/her information you may need to update every contact document referencing them.

wdberkeley
  • 11,531
  • 1
  • 28
  • 23
  • I am using GridFS for the photo now by the way (no blob). If you think it can be done it a better way please let me know! :) – Moody Mar 19 '15 at 22:55