2

I am new to Node.js and Mongoose and need some help. So I first create an array called beerObjects. Then I make a request to breweryDB and store info in this array.

request(options, function (error, response, body) {
            if (error) throw new Error(error);
            obj = JSON.parse(body);
            data = obj['data'];
            for(i = 0; i < data.length; i++) {
                var newBeer = new Beer();
                newBeer.id = data[i]['id'];
                newBeer.name = data[i]['name'];
                newBeer.description = data[i]['description'];
                newBeer.abv = data[i]['abv'];
                if (data[i].hasOwnProperty('labels')) {
                    newBeer.image = data[i]['labels']['large'];
                }

                beerObjects.push(newBeer);
                console.log(beerObjects[i].name);
            }
            addBeersToDatabase(beerObjects);
        });

I have another function that will take this array and store the info in my mongo database.

function addBeersToDatabase(beerObjects) {
console.log(beerObjects.length);
for (i = 0; i < beerObjects.length; i++) {
    console.log(beerObjects[i].id);
    // check if beer is already in database
    Beer.count({id: beerObjects[i].id}, function(err, count){
        if (err) {
            handleError(err);
        }
        if (count == 0) {
            // add new beer to database
            var newBeer = new Beer();
            newBeer.id = beerObjects[i].id;
            newBeer.name = beerObjects[i].name;
            newBeer.description = beerObjects[i].description;
            newBeer.abv = beerObjects[i].abv;
            newBeer.image = beerObjects[i].image;

            newBeer.save(function(err) {
                if (err) {
                    throw err;
                }
            });

        }
        else {
            // beer is already in database
        }
    });
}

}

In the beginning of the addBeerToDatabase() function, beerObject is defined and the console.log() statements output the correct information. But inside the Mongoose function Beer.count(), I get this error message.

newBeer.id = beerObjects[i].id;
TypeError: Cannot read property 'id' of undefined

This 'id' is the id of beerObjects[i], not newBeer. How do I correctly pass beerObjects to the mongoose function and use it in that function?

EDIT:

function addBeersToDatabase(beerObjects) {
for (i = 0; i < beerObjects.length; i++) {
    console.log(beerObjects[i].beerId);
    var currentBeer = beerObjects[i];

    // check if beer is already in database
    Beer.findOne({'beerId': currentBeer.beerId}, function(err, beer){
        if (err) {
            handleError(err);
        }
        if (beer) {
            // beer is already in database
        }
        else {
            // add new beer to database
            console.log(currentBeer.name);
            saveNewBeer(currentBeer);
        }
    });
}

}

function saveNewBeer(currentBeer) {
var newBeer = new Beer();
newBeer.beerId = currentBeer.beerId;
newBeer.name = currentBeer.name;
newBeer.description = currentBeer.description;
newBeer.abv = currentBeer.abv;
newBeer.image = currentBeer.image;

newBeer.save(function(err) {
    if (err) {
        throw err;
    }
});

}

This code is adding n duplicates (where n = beerObjects.length) of just the last item in beerObjects.

1
  • i variable is defined out of scope, you should do it the local or store id in the function local var: var id = beerObjects[i].id; Commented Apr 7, 2016 at 21:57

3 Answers 3

1

Edit:

You are looping through and 'grabbing' a beer with beerObject[i].id, then you asynchronously check the count, by the time you get down to setting newBeer.id you are in a different scope. The remedy to this is to set a variable to beerObject[i].id and pass that in as the 'beer' you look for in the Beer.count:

like so:

for (i = 0; i < beerObjects.length; i++) {
    console.log(beerObjects[i].id);
    var checkBeer = beerObjects[i]
    // check if beer is already in database
    Beer.count({id: checkBeer.id}, function(err, count){
        if (err) {
            handleError(err);
        }
        if (count == 0) {
            // add new beer to database
            var newBeer = new Beer();
            newBeer.id = checkBeer.id;
... and so on
Sign up to request clarification or add additional context in comments.

5 Comments

Same as the other answer. Still doesn't work. I created a field called 'id' which is the id of the beer. '_id' is different, that's the mongodb id. So it's not a problem with newBeer, it's a problem with beerObjects.
Yes this solved my original problem but now I have another issue. Only the last beer in the list is getting added to my database. Let's say the list length is 10. It is adding 10 copies of the same beer to the database.
I'm using findOne now and it's still not working. I even tried match the name instead of id but it's still adding duplicates. And the for loop is still looping several times with just the last beer.
Yes i put it in a new function. Take a look at the edited question.
1

You need to use _id instead of id :

newBeer._id = data[i]['id'];
newBeer.name = data[i]['name'];

1 Comment

Still doesn't work. I created a field called 'id' which is the id of the beer. '_id' is different, that's the mongodb id. So it's not a problem with newBeer, it's a problem with beerObjects.
1

MongoDB ID is auto-generated so you cannot added any values into _id property unless you defined _id as String in your mongoose model.

For example.

var mongoose = require('mongoose');
var beerSchema = new mongoose.Schema({
    _id: String,
    name: String,
    // rest of beer properties
});

module.exports = mongoose.model('Beer', beerSchema);

Inside your function,

function addBeersToDatabase(beerObjects) {
    for (i = 0; i < beerObjects.length; i++) {
    Beer.findbyId(beerObjects[i].id, function(err, beers){
        if (beers.lenght == 0) {
            // add new beer to database
            var newBeer = new Beer();
            newBeer._id = beerObjects[i].id;
            newBeer.name = beerObjects[i].name;
            newBeer.description = beerObjects[i].description;
            newBeer.abv = beerObjects[i].abv;
            newBeer.image = beerObjects[i].image;
            newBeer.save();
        }
        else {
            // beer is already in database
        }
    });
}

If you want to use default mongoId, you just need to remove _id: String in model and newBeer._id = beerObjects[i]id from your function. I hope this would help you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.