简体   繁体   中英

mongoose db returning data from two documents

I am creating my first mongoose database app. I am trying to write an express API call that returns an object that contains data from two documents. Whenever I call the /data route I get an empty array back. I added two console.log lines and the output is:

test2
test1

What can I do to have the forEach finish before returning the result?

Here's the code:

router.route('/data')
//get all data
.get(function(req, res) {
    var results = [];
    Attendee.find(function(err, attendees) {
        if (err) {res.send(err);}
        else {
            attendees.forEach(function(attendee) {

                Message.find({userID: attendee._id}, function(err,messages){
                    results.push({
                        attendee: attendee,
                        messages: messages
                    });
                });
                console.log("test1");
                console.log(results);
            });
            console.log("test2");
            res.json(results);
        }
    });
});

This is the result I would like to get

[ { attendee: 
 { _id: 53c060e7fb90e3d709d6bdae,
   fullName: ‘joe smith,
   phoneNumber: '+555’,
   __v: 0 },
messages: 
 [ { _id: 53c06887fb1d24fb095fd365,
     phoneNumber: '+555',
     body: ‘test’,
     userID: '53c060e7fb90e3d709d6bdae',
     sid: 'SMa86f2914986d4b04067d7f054da205a5',
     __v: 0 },
   { _id: 53c41cf3d068393d17dc0dbf,
     phoneNumber: '+555',
     body: ‘test’,
     userID: '53c060e7fb90e3d709d6bdae',
     sid: 'SM4f6c64ca7b39e6caee9859e761a2850d',
     __v: 0 },
   { _id: 53c421e16371e54f171751cf,
     phoneNumber: '+555',
     body: ‘test’,
     userID: '53c060e7fb90e3d709d6bdae',
     sid: 'SM1097eae33e4f53cdcdad32651c016437',
     __v: 0 },
   { _id: 53c421e16371e54f171751d0,
     phoneNumber: '+555',
     body: ‘test’,
     userID: '53c060e7fb90e3d709d6bdae',
     sid: 'SM5a452e51c995d7ad6ad8f7b85cec80b0',
     __v: 0 } ] } ]

The primary issue is that you are sending back the results in the response before they have been fully retrieved. Your res.json(results) is outside the Message.find(...) callback. Additionally, since you push the attendee object onto the results array in that same callback, it too will be missing, and your returned results array will simply be the original empty array.

You need something more like this:

router.route('/data')
//get all data
.get(function(req, res) {
    var results = [];
    Attendee.find(function(err, attendees) {
        if (err) {res.send(err);}
        else {
            q.all(attendees.map(function(attendee) {
                return Message
                    .find({userID: attendee._id}, "")
                    .exec()
                    .then(function(messages) {
                        results.push({
                            attendee: attendee,
                            messages: messages
                        });         
                     })
            }))
            .then(function() {
                res.json(results);
            })
        }
    });
});

I solved my own problem by using a mongoose feature called populate. http://mongoosejs.com/docs/populate.html . I was able to simplify my code a lot:

    router.route('/data')
    //get all data
    .get(function(req, res) {
        Attendee.find().populate('messages').exec(function(err, attendees){
            if (err) {res.send(err);}
            res.json(attendees);
        });
    }); 

The real magic of this code is in the schemes:

var mongoose = require('mongoose');

var AttendeeSchema = new mongoose.Schema({
    fullName: {
        type: String,
        require: true
    },
    dateJoined: {
        type: Date,
        require: true
    },
    phoneNumber: {
        type: String,
        required: true
    },
    messages: [{
        type: mongoose.Schema.Types.ObjectId, ref: "Message"
    }]
});

module.exports = mongoose.model('Attendee', AttendeeSchema);

and

var mongoose = require('mongoose');

var MessageSchema = new mongoose.Schema({
    _userID: {
        type: String,
        ref: 'Attendee'
    },
    phoneNumber: {
        type: String,
        require: true
    },
    date: {
        type: Date,
        require: true
    },
    body: {
        type: String,
        required: true
    },
    sid: {
        type: String,
        required: true
    }

});

module.exports = mongoose.model('Message', MessageSchema);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM