catastrophic error
catastrophic error

Reputation: 390

One to many association on Sails 0.10.x fails to retrieve owner data using populate

I'm trying to create a simple one-to-many assocation using sails 0.10.x with mongoDB. I have two models, Game and Map, which a game can have multiple maps associated to its account. Using populate I can correctly get all the maps associated to the game, but the inverse operation doesn't work. I cannot get the game data using populate from Map.

here are my models:

//Game.js
module.exports = {  
   attributes: {
    name:{
       type: 'string',
       required: true
     },

   maps: {
      collection: 'map',
      via: 'game'
   }
}

//Map.js
module.exports = {
    attributes: {    
        name: {
           type: 'string',
           required: true
     },

game:{
     model: 'game'
  }
}

//test data:
  Game.create({
    id: 200,
    name: 'game1'});

  Map.create({
    id: 300,
    name: 'map1',
    game: 200
  });

If I use

Game.find().populate("maps").exec(console.log);

it correclty returns the maps associated to the game:

 { maps: 
 [ { name: 'map1',
     game: '200',
     id: '300' } ],
  name: 'game1'}

but the inverse command, trying to retrieve the game data from map, returns a undefined game property:

Map.find().populate("game").exec(console.log)

returns:

{ name: 'map1',
  game: undefined,
  id: '300' }

Even trying using a parameter in find(), I got the same result.

Double checked my code with the Sails and waterline documentation but could't figure out what I'm doing wrong.

Sails doc.: http://sailsjs.org/#/documentation/concepts/ORM/Associations/OnetoMany.html

Waterline doc.:https://github.com/balderdashy/waterline-docs/blob/master/associations.md

UPDATE

I figured out that, if I create the test data without forcing the IDs I want, it works perfectly:

  Game.create({name: 'game1'}).exec(console.log);

  Game.findOne({name: 'game1'}, function (err, game){
    Map.create({
      name: 'map1',
      game: game.id
    }).exec(console.log);
  });

now I can get the owner data. Since it works when I use the mongoDB ids, I believe it is some issue related to the connector.

Map.find().populate("game").exec(console.log)
//returns (ommited the original IDs
   [ { game:
     { name: 'game1',  id: 'xxx100' }, 
     name: 'map1',
     id: 'xxx300' } ] 

Thanks!

Upvotes: 4

Views: 947

Answers (2)

catastrophic error
catastrophic error

Reputation: 390

I figured out that, if I create the test data without forcing the IDs I want, it works perfectly:

Game.create({name: 'game1'}).exec(console.log);

Game.findOne({name: 'game1'}, function (err, game){
 Map.create({
   name: 'map1',
   game: game.id
 }).exec(console.log);
});

now I can get the owner data.

Since it works when I use the mongoDB ids, I believe it is some issue related to the connector.

Map.find().populate("game").exec(console.log)
//returns (ommited the original IDs)
 [ { game:
    { name: 'game1',  id: 'xxx100' }, 
      name: 'map1',
      id: 'xxx300' 
     } 
 ] 

Upvotes: 0

sgress454
sgress454

Reputation: 24948

If you're using MongoDB and you don't want to use the default Mongo IDs, you need to configure your models accordingly. For example:

//Game.js
module.exports = {  
   // Don't use automatic primary key
   autoPK: false,
   attributes: {
    // Create your own ID field manually
     id: {
       type: 'integer',
       primaryKey: true
     },
     name:{
       type: 'string',
       required: true
     },

     maps: {
      collection: 'map',
      via: 'game'
     }

   }
}

This will allow associations and other operations to work correctly. Mind you, if you do this then you'll be responsible for guaranteeing unique integer IDs; MongoDB doesn't have an "autoincrement" property.

Upvotes: 1

Related Questions