Question

My database looks like this:

{
 _id: 1,
 values: [ 1, 2, 3, 4, 5 ]
},
{
 _id: 2,
 values: [ 2, 4, 6, 8, 10 ]
}, ...

I'd like to update every value in every document's nested array ("values") that meets some criterion. For instance, I'd like to increment every value that's >= 4 by one, which ought to yield:

{
 _id: 1,
 values: [ 1, 2, 3, 5, 6 ]
},
{
 _id: 2,
 values: [ 2, 5, 7, 8, 11 ]
}, ...

I'm used to working with SQL, where the nested array would be a seperated table connected with a unique ID. I'm a little lost in this new NoSQL world.

Thank you kindly,

Was it helpful?

Solution

This sort of update is not really possible using nested arrays, the reason for this is given in the positional $ operator documentation, and that states that you can only match the first array element for a given condition in the query.

So a statement like this:

db.collection.update(
    { "values": { "$gte": 4 } },
    { "$inc": { "values.$": 1 } }
)

Will not work in the sense that only the "first" array element that was matched would be incremented. So on your first document you would get this:

{ "_id" : 1, "values" : [  1,  2,  3,  6,  6 ] }

In order to update the values as you are suggesting you would need to iterate the documents and the array elements to produce the result:

db.collecction.find({ "values": { "$gte": 4 } }).forEach(function(doc) {
    for ( var i=0; i < doc.values.length; i++ ) {
        if ( doc.values[i] >= 4 ) {
            doc.values[i]++;
        }
    }
    db.collection.update(
        { "_id": doc._id },
        { "$set": { "values": doc.values } }
    );
})

Or whatever code equivalent of that basic concept.

Generally speaking, this sort of update does not lend itself well to a structure that contains elements in an array. If that is really your need, then the elements are better off listed within a separate collection.

Then again, the presentation of this question is more of a "hypothetical" situation without understanding your actual use case for performing this sort of udpate. So if you possibly described what you actually need to do and how your data really looks in another question, then that might get a more meaningful response in terms of the best approach for you to use.

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