Meteor MongoDB design question

Hello. I’m still a newbie and I’m working on my first production app (I’ve only been a hobbyist until this project). I have a question about designing my database and the performance in Meteor/MongoDB…

As an example, consider the Todos sample application. There is a Tasks database with the individual tasks and a Lists database with each user list. When creating a task, the _id of the List that it belongs to is entered.

What is the best way to design my database if I will not have user lists, but a fixed set of lists defined by the application? Some of the lists may be separate, some are auto generated, and tasks could belong to more than one of these at a time. For example:

  1. Inbox
  2. Today
  3. All Tasks

A task could be in the Inbox or All Tasks, but not both at the same time. A task with a due date of today will appear in All Tasks, but would automatically be included in the Today list as well.

I think it makes the most sense to have a single list and use fields to designate Inbox vs All Tasks, and then a database search that would retrieve tasks with a due date of Today. If I do that, should I just use the list names, or somehow generate a unique key? (And how would I do that for a fixed set of application-defined lists?)

What about performance? Would these possible more complex searches cause performance problems, or am I overthinking this?

In case it make a difference to the answer, this is a Meteor-React app. Thanks in advance!

Ken

Don’t put tasks in lists like Inbox or Today.
Assuming Inbox is some form of “unread” or “non-archived” task or something like that, I’d just have a field on the task that says active: true/false or something like that.
var inboxTasks = Tasks.find({active: true})

Today-tasks should just be a timestamp that’s processed live. Absolutely not something you have to set and “upkeep” by some continuous async task.

I normally use unix timestamps for alot of my stuff so here’s my logic on that, although I’m sure Mongo has ISODate queries as well you should look into.

var todayTasks = Tasks.find({
due: {$gte: moment().startOf(‘day’).unix() , $lte: moment().endOf(‘day’).unix()}
})

var allTasks = Tasks.find()

Now if you want to do userconfigured lists, just make a Lists collection
Example:
{
name: "MyList"
owner: "my_user_id_from_Meteor.userId()"
tasks: []
}

To add:
Lists.update(listID, {$push: {tasks: taskID}});
Remove: replace push with pull

To list tasks from a given list:
var list = Lists.findOne() //Whatever logic you need here. Just any list object.
Tasks.find({_id: {$in: list.tasks}})

This way you may have tasks in multiple lists if desirable, and allows you to create special lists as well.

As for performance, a lot of people overthink this. Don’t care about performance unless you know from the start that you’re gonna have thousands of users online at the same time. If it’s not some huge megaproject, worry about performance when you need to. A lot can be solved with MongoDB indicies. Most of the delay comes from network delay. Not DB or app-delay :slight_smile: Your DB design is seldom the first source of performance shortages! If it is, then you should go read a book :stuck_out_tongue:

IDs are always indexed. but if you’re gonna index stuff like today, I’d index the due-field in tasks with the highest numbers first(I think it’s -1. I always have to look that up).
As well as the owner-field.
Anything you query, or query together, you create as an index(together if multiple fields). Indicies increase performance but increase disk space usage(which is REALLY cheap).

Don’t bother unless it’s actually the DB. Use Kadira to check the time usage.

I once optimized mySQL queries that took a workday to run(really…) to run within a couple of seconds joining millions of rows on a fairly normal computer. Took up a few gigs of space though.

I wrote this in plain old JS, but since you’re running react, you’re likely running ES6, so just replace “var” with let/const where suitable for you :smile: