Creating mongoose.js object with multiple 'ref' fields. (Or: how to switch to a nosql, event driven mindset)

StackOverflow https://stackoverflow.com/questions/23624944

  •  21-07-2023
  •  | 
  •  

Domanda

First of all, I'm coming from years of using Django and relational databases, but want to try something new - so this is probably a conceptual problem on my part. I'm just not sure where it is. Hope the question is clear enough, even though I'm not sure what I should be asking...

So. I'm setting up an application that contains Teams, and Matches between these teams.

Here are my models:

var TeamSchema = new Schema({
  name: String,
  code: String
});

TeamSchema.statics = {
  list: function(options, cb) {
    var criteria = options.criteria || {};
    this.find(criteria)
      .exec(cb);
  },
  load: function(id, cb) {
    this.findOne({_id: id})
      .exec(cb);
  },
};

var MatchSchema = new Schema({
  home_team: { type: Schema.ObjectId, ref: 'Team' },
  away_team: { type: Schema.ObjectId, ref: 'Team' },
  datetime: Date,
  slug: String,
  home_score: Number,
  away_score: Number
});

Where I run into problems is when I want to populate these models programmatically. The teams are easy enough:

// Clear old teams, then add default teams
Team.find({}).remove(function() {
  Team.create({
    name: 'Brazil',
    code: 'bra'
  }, {
    name: 'Cameroon',
    code: 'cmr'
  }, {
    name: 'Spain',
    code: 'esp'
  }, {
....

But then I want to create matches, which requires getting the _ids for the teams. In my way of thinking this is pretty easy: Create the Teams, then before creating the Matches fetch the appropriate Teams and assign to variables, and finally create a Match using these variables to populate the home_team and away_team fields.

This of course doesn't work here, since there's no guarantee the Teams have been populated when the Match creating function is called. So I moved that code to the callback of the Team creation code. But still that didn't work, since when the Match is created the Team variables are still not populated. I sort of got this to work by putting the match creation code as a callback to the Team lookup (which itself is a callback to the Team creation code). But that only works for ONE of the Teams, how do I ensure I have both the _ids available before creating a Match?

As I said in the beginning, I feel like I'm thinking about this the wrong way - so I'm not necessarily looking for working code, more for pointers about where I'm going wrong in my thinking.

That said, this is the working code I have for setting one of the teams:

// Clear old teams, then add default teams
Team.find({}).remove(function() {
  Team.create({
    name: 'Brazil',
    code: 'bra'
  }, {
    name: 'Croatia',
    code: 'hrv'
  }, 
  function() {
    console.log('finished populating teams');
    // Clear old matches, then add default matches
    Match.find({}).remove(function() {
      Team.findOne({code: 'bra'}, function(err, obj) {
        if (!err) {
          console.log(obj.code);
          Match.create({
            datetime: "2014-06-01T22:00:00.000Z",
            slug: 'bra-hrv',
            home_team: obj._id
         });
       } else {
         console.log(err);
       }
     });
    });
  });
});

Edit: Found one way around it. Since code is unique to each team, I switched the team _id field to String and removed code. That way I can easily create the Match objects without having to look up the _id - I already know what it is.

Doesn't really solve my underlying problem, but it does get the work done.

È stato utile?

Soluzione

If you use new and save to create your Team docs you'll have immediate access to their _id values because they're assigned client-side:

var brazil = new Team({
    name: 'Brazil',
    code: 'bra'
  });
brazil.save();
var croatia = new Team({
    name: 'Croatia',
    code: 'hrv'
  });
croatia.save();

Match.create({
  datetime: "2014-06-01T22:00:00.000Z",
  slug: 'bra-hrv',
  home_team: brazil._id,
  away_team: croatia._id
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top