Question

I'm writing a procedure that will take an array of strings such as

var mywords = ["cat", "dog", "fish"] 

and upsert them into a MongoDb collection (called the 'words' collection). I would like to keep a count of how many times each word has been inserted into the collection. It is possible that some of the words are already in the collection and some are not.

This works:

var my_func = function(mywords) {
    //Get connection to db...

    mywords.forEach(function(word) {
        collection.update({name: word}, {$inc: {count: 1}}, {upsert: true});
    });
}

Awesome. So now if {name: dog, count: 3} was the only document in the collection and I run my_func(["cat", "dog", "fish"]), then the collection will now contain:

{name: dog, count: 4, _id: blah}
{name: cat, count: 1, _id: blah}
{name: fish, count: 1, _id: blah}

This is exactly what I want except I would like to do this all in one update, ie. not within a forEach. I tried this:

var broken_func = function(mywords) {
    //Get connection to db...

    collection.update({name: {$in : {mywords}}, {$inc: {count: 1}}, {upsert: true, multi:true});
}

However, if I start with the same collection which only contains {name: dog, count: 3} and run my_func(["cat", "dog", "fish"]), my collection looks like this:

{name: dog, count: 3}
{count: 1}

I want MongoDb to match the name field of a document with any string in the mywords array and increment the count field of that document. If there is no document name field equal to some string in mywords, create a document {name: "stringFrom_mywords", count:1}.

Is what I want to do possible and how can I achieve the behavior I want? I feel that using forEach and doing separate updates is inefficient. I happen to be using the node.js MongoDb driver if you find that information useful. I am aware that my problem is similar to this ruby question Upsert Multiple Records with MongoDb

Was it helpful?

Solution

While you can run an update with both the upsert and multi flags, it will not have the effect that you want. You will need to run three individual upsert commands, as you are doing with your forEach example.

If you would like to have this feature added to a future relase of MongoDB, feel free to open a Jira ticket in the SERVER project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top