How can I add/remove user specific data in Meteor

502 Views Asked by At

A few questions about storing user data in MongoDB. What is the best place in mongo to store user specific data, such as User settings, User photo url, User friends, User events?

In Mongo, user data is stored in: Meteor

  / Collections
    / users
      / _id
        / profile
        / services

Should I add there a new collections? In a following way:

        / events / _id's
        / friends / _id's
        / messages / _id's
        / settings

How should I publish user's private data and manipulate this collections, to be sure it's save and no one else will modify or have access to private data of another person.

2

There are 2 best solutions below

2
On

Normalization

"Database normalization is the process of organizing the attributes and tables of a relational database to minimize data redundancy."

MongoDB is a non relational database. This makes normalized data hard to query for. This is why in MongoDB we denormalize data. That makes querying for it easier.

It depends on your use-case. The question is basically when to demormalize. It's mostly a matter of opinion. But objective here are some pros and cons:

Pros to demormalization

  • It's easier to retrieve data (Due to Mongo not beeing a relational DB)
  • It performs better if you are always getting the data in bulk

Cons to demormalization

  • It doesn't scale well for things like user.messages (You can't just publicize some messages)

In your case I'd definitly go for seperate collections for events, friends and messages. Setting can't expand infinitly. So I'd put it into the users collection.

Security

I'd use a publications and allow and deny for this. Let me make an example for Messages:

Collection

Messages = new Mongo.Collection('Messages')

Messages.insert({
  sender: Meteor.userId,
  recipient: Meteor.users.findOne()._id,
  message: 'Hello world!'
})

Publication

Meteor.publish('userMessages', function (limit) {
  return Messages.subscribe({
    $or: [
      {sender: this.userId},
      {recipient: this.userId}
    ]
  }, {limit: limit})
})

Allow

function ownsMessage (user, msg) {
  return msg.sender === user ? true : false
}

Messages.allow({
  insert: function (userId, newDoc) {
    !!userId
  },
  update: function (userId, oldDoc, newDoc) {
    if(
      ownsMessage(userId, oldDoc) &&
      ownsMessage(userId, newDoc)
    ) return true
    return false
  },
  remove: function () {
    return false
  }
})

This code is untested, so it might contain small errors

1
On

You can add data to the users profile field like this:

Meteor.users.update( id, { $set: { 'profile.friends': someValue } } );

To only publish specific fields you can do something like this:

Meteor.publish( 'users', function () {
    return Meteor.users.find( {}, { fields: { 'profile.friends': 1 } } );
});

Hope this helps.