3

Just started to play around with node.js, have some past experience with JavaScript but very little in server-side.

I have the below code and the functionality that I'm looking for is too add a product to the collection using Mongoose, however, if a duplicate is found using 'name', then push the product as an embedded document to the duplicate, with only select information, such as product_ids, package info, etc. I'm assuming that the problem has to do with findOne not finding any duplicates on the first run. If I run it a second time, it does detect the duplicates, but by then it's too late. I'm not sure how to get findOne to run only after the previous 'save' occurred.

function insertProduct(data) {
    var product;
    Product.findOne({
        name: data.name
    }, function(err, doc) {
        if (err) throw err;
        if (!doc) {
            product = new Product({
                name: data.name
                //other product data
            });
            product.packages.push({
                //package data
            });
        }
        else if (doc) {
            doc.packages.push({
                //package data
            });
            product = doc;
        }
        product.save(function(err) {
            if (err) throw err;
            console.log('Added: ' + product.name);
        });
    });
}

request(url, function(error, response, body) {
   if (!error && response.statusCode === 200) {
      jsonResult = JSON.parse(body);
      jsonResult.result.forEach(insertProduct);
   }
});

I realize this has to be an issue with control flow, that I'm still trying to get a hold of. Your help is appreciated!

1 Answer 1

1

Welcome to the world of non-blocking IO, and JavaScript closures :)

A simpler way around it is by separating the product creation and push the packages after the product is successfully created.

addProduct = function(name, next) {
  Product.findOne({name: name}, function(err, doc) {
    if(doc) {
      next(null, doc);
    }
    else {
      // create new product...
      var d = new Product({name: name});
      next(null, d);
    }
  });
});

// ... snipped

jsonResult.result.forEach(function(item) {
  addProduct(item.name, function(err, doc) {
    if(err == null) {
      doc.packages.push({
        // stuffs
      });
      doc.save();
    }
  });
});
Sign up to request clarification or add additional context in comments.

1 Comment

Definitely a more logical way of going at it, but it doesn't seem to do the trick. Product.findOne only finds a duplicate the second time I run the app. On the first run, starting from an empty collection, it doesn't see any of the newly created documents for some reason, so it can't find the duplicate. Any other ideas? Thanks again!

Your Answer

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