defect
defect

Reputation: 558

Adding a new object to an array within a Mongo document through Meteor

I'm writing a little planning poker tool in Meteor; first time working with meteor and json document stores. I have a Collection for user stories, along with the users assigned to that story and ratings from those users.

Initially I'll do some inserts like this:

Stories.insert({'story': stories[i], 'assignees': users, 'ratings': []});

... and one entry might look like this:

{
  'story': 'some story',
  'assignees': ['Bob', 'Joe'],
  'ratings': []
}

Then, once a user has entered their rating for that story, it should be updated to look something like this:

{
  'story': 'some story',
  'assignees': ['Bob', 'Joe'],
  'ratings': [{'Bob': 2}, {'Joe': 5}] // maybe a better way to do this?
}

I'm having trouble writing the line to make that happen. What I have now is:

var users = ['Bob', 'Joe'];
for (var i = 0; i < users.length; i++) {
  var user = users[i];
  var rating = {user: 1};
  Stories.update({}, {$push: {'ratings': rating}});
}

Unfortunately, the result is something like:

{
  'story': 'some story',
  'assignees': ['Bob', 'Joe'],
  'ratings': [{user: 1}]
}

That is, only one object in the ratings array, and not even of the correct key (plain user instead of something like Bob). This may have something to do with JS hoisting and object instantiation being tricky. Any insight is appreciated.

Upvotes: 0

Views: 940

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151072

Your problem is you are trying to use a variable as a "key" for the object, which does not work that way. User the bracket [] notation in order to dynamically assign the "key" instead as follows:

var users = ['Bob', 'Joe'];
for (var i = 0; i < users.length; i++) {
  var user = users[i];
  var rating = {};
  rating[user] = 1;
  Stories.update({}, {$push: {'ratings': rating}});
}

Actually you can even do this better with a single update:

var users = ['Bob', 'Joe'];
var ratings = [];
for (var i = 0; i < users.length; i++) {
  var user = users[i];
  var rating = {};
  rating[user] = 1;
  ratings.push( rating);
}

Stories.update({}, {$push: {'ratings': { $each: ratings } }});

So the $each modifier allows you to push an "array" of new documents onto the existing array and this means less updates over the network.

Not sure where you are doing this operation from so that second choice may not be available from a browser client with minimongo. But it can be invoked that way from the server.

Upvotes: 4

Related Questions