ibocon
ibocon

Reputation: 1494

How to properly use Mongoose query, Find and update object array

Here is Main Code to look into

function update(feed){
//.. do set up
var target = feed.title;
var value = {index: feed.value};

var query = { test: target, 'array.index': {$ne: value.index} },
    update = { $push : {"array" : value} },
    options = { upsert: true, new: true };

Model.findOneAndUpdate(query, update, options, function(err, docs) {
        if(err) throw err;
        console.log(docs);
    }
);}

(I modified the code to be general. if you need specific code, just ask me to update this post)

I am trying to do Model.findOneandUpdate with upsert: true.
My code executes when specific event emitted

feedparser.on('readable', function() {
    update(this.read());
});

Becasue of 'array.index': {$ne: value.index} query, the code creates new one after the first execution.

Therefore,

db.collection.find()

returns multiple documents that has same property with different ObjectId.
For Example,

{"_id":ObjectId("1"), test: "A", array:[{index:"1"}]}
{"_id":ObjectId("2"), test: "A", array:[{index:"1"}]}

I want to be the code do

  1. Check document exist or not.
  2. if Exist, add new value to the Document's array. Also, new value should be unique by index.
  3. if NOT Exist, create new Document and add new value to new Document's array.

UPDATE:
I also try to do it by

var doc = Model.findOne({ test: target });

if(doc != null){
    var query = { _id: doc._id, 'array.index': {$ne: value.index} };
    var update = { $push : {"array" : value} };
    var options = {new: true};
    Model.update(query, update, options, function(err, d){
        if(err) throw err;
        console.log(d);
    });

}else{
    doc = {
        test: target,
        array:[value]
    };

    Model.create(doc, function (err, res){
        if(err) throw err;
        console.log(res);
    });
}

This code result in do Nothing.

UPDATE
I also try this by

Model.findOne({ test:target }, function(err, doc){
    if(doc === null){
        doc = {
            test: target
            arrays:[value]
        };

        Animation.create(doc, {new: true}, function (err, res){
            if(err) throw err;
            console.log(res);
        });
    }else{
        var query = { _id: doc._id, 'arrays.index': {$ne: value.index} };
        var update = { $push : {"arrays" : value} };
        var options = {new: true};
        Animation.update(query, update, options, function(err, res){
            if(err) throw err;
            console.log(res);
        });
    }
});

But, it create new Document by each different index value.

UPDATE

var query = { test: target, 'array:index': {$ne: value.index} };
var update = { $push : {'array' : value}};
var options = {new: true};
Model.findOneAndUpdate(query, update, options, function(err, doc){
    if(err) throw err;
    if(doc === null){
        doc = new Model({
            test: target,
            array:[value]
        });
        doc.save();
    }
});

It also does not work...

Upvotes: 0

Views: 883

Answers (1)

ibocon
ibocon

Reputation: 1494

I found how to solve this problem! First, the reason why the problem arise is I am trying to do upsert with $ne. Here is my code,

Animation.findOne({ title: AnimationTitle, team: TeamName }, function(err, result){
        if(err) { throw err; }
        if(result){
            Animation.findOneAndUpdate({ title: AnimationTitle, team: TeamName, 'episodes.number': {$ne: episode.number} }, { $addToSet : {'episodes' : episode}}, {new: true}, function(err, result){
                if(err) { throw err; }
            });
        }else{
            Animation.findOneAndUpdate({ title: AnimationTitle, team: TeamName }, { $addToSet : {'episodes' : episode}}, {new: true, upsert: true}, function(err, result){
                if(err) { throw err; }
            });
        }

    });

Upvotes: 0

Related Questions