ffritz
ffritz

Reputation: 2261

Populate from two collections

I have 2 Schemas defined for 2 different collections, and I need to populate one of them into the other:

stationmodel.js

var stationSchema = new Schema({ 
    StationName: 'string', 
    _id: 'number', 
    Tripcount: [{ type: Schema.Types.ObjectId, ref: 'Tripcount'}]
},
    {collection: 'stations'}
);
module.exports = mongoose.model('Station', stationSchema);

tripmodel.js

var tripSchema = new Schema({
    _id: { type: Number, ref: 'Station'},
    Tripcount: 'number'
},
    {collection: 'trips'}
);
module.exports = mongoose.model('Tripcount', tripSchema);

According to the mongoose populate documentation, this is the way to go. I have the problem that "Tripcount" remains as [] when I use Postman to GET the stations.

My DB Structure for the 'stations' collection:

{
    "_id": 1,
    "StationName": "Station A",
}

And for the 'trips' collection:

{
    "_id": 1,
    "Tripcount": 6
}

My routes.js:

module.exports = function(app) {

    app.get('/stations', function(req,res) {
        var query = Station.find().populate('Tripcount');
        query.exec(function(err, stations){
            if(err)
                res.send(err);
            res.json(stations);
        });
    });

};

I can't seem to find the error, maybe someone here can spot a mistake I made.

Upvotes: 1

Views: 1539

Answers (1)

chridam
chridam

Reputation: 103375

You are enclosing the mongoose SchemaTypes in single quotes, you either need to reference the SchemaTypes directly when you define a property in your documents which will be cast to its associated SchemaType.

For example, when you define the Tripcount in the tripSchema it should be cast to the Number SchemaType as

var tripSchema = new Schema({
    _id: Number,
    Tripcount: Number
}, {collection: 'trips'});

module.exports = mongoose.model('Tripcount', tripSchema);

and the station schema

var stationSchema = new Schema({ 
    _id: Number, 
    StationName: String, 
    Tripcount: [{ type: Number, ref: 'Tripcount'}]
}, {collection: 'stations'});

module.exports = mongoose.model('Station', stationSchema);

Then in your stations collection, the documents would ideally have the structure

{
    "_id": 1,
    "StationName": "Station A",
    "Tripcount": [1]
}

for the populate method to work, of which when applied as

Station.find().populate('Tripcount').exec(function(err, docs){
    if (err) throw err;
    console.log(docs);  
    // prints { "_id": 1, "StationName": "Station A",   "Tripcount": [{"_id": 1, Tripcount: 6 }] }
});

Alternative Approach

Another approach that you could take if the station collection does not have Tripcount field is to use the $lookup operator found in the aggregation framework as:

Station.aggregate([
    { 
        "$lookup": {
            "from": "tripcollection",
            "localField": "_id",
            "foreignField": "_id",
            "as": "trips"
        }
    },
    {
        "$project": {
            "StationName": 1,
            "trips": { "$arrayElemAt": ["$trips", 0] }
        }
    },
    {
        "$project": {
            "StationName": 1,
            "Tripcount": "$trips.Tripcount"
        }
    }
]).exec(function(err, docs){
    if (err) throw err;
    console.log(docs);  
    // prints [{ "_id": 1, "StationName": "Station A",  "Tripcount": 6 }] }
});

Upvotes: 1

Related Questions