0

I know I can do something like this to update the field to a specific value:

db.coll.update({},{ $set: {'fieldName': 'fieldValue' } }, { multi:true });

However, I need to update the value of a field equal to the number of values in an array field of the same document. I know this probably requires aggregate function but am newer to Mongo and could use some help constructing the query. It also needs to be done for every document in the collection.

SKeney
  • 1,965
  • 2
  • 8
  • 30
  • Does this answer your question? [Update MongoDB field using value of another field](https://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field) – whoami - fakeFaceTrueSoul May 06 '20 at 04:01

2 Answers2

1

Let's assume that our collection looks like below:

{
        "_id" : 1
        "array" : [
                1,
                2,
                3
        ]
},
{       "_id" : 2,
        "array" : [
                1
         ]
},
{
        "_id" : 3
        "array" : [
                1,
                2,
                3,
                4,
                5,
                6
        ]
}

The required query is :

db.collection.update({},[{$set: {size: {$size: '$array'}}}], {multi: true})

Below will be the updated collection:

{
        "_id" : 1,
        "array" : [
                1,
                2,
                3
        ],
        "size" : 3
}
{
        "_id" : 2,
        "array" : [
                1
        ],
        "size" : 1
}
{
        "_id" : 3,
        "array" : [
                1,
                2,
                3,
                4,
                5,
                6
        ],
        "size" : 6
}
ngShravil.py
  • 4,742
  • 3
  • 18
  • 30
  • The dollar ($) prefixed field '$size' in 'likeCount.$size' is not valid for storage. That is what I get as a response when trying the following – SKeney May 06 '20 at 14:25
  • This is what I understood as the minimum requirement from the OP. Could you explain the question more? Like how your collection looks like. It will be easy to investigate. – ngShravil.py May 06 '20 at 15:38
  • I think you are getting confused between `size` and `$size`, `size` is the field name and `$size` is an aggregator operator. – ngShravil.py May 06 '20 at 15:45
  • Yeah I know I replaced ```size``` with ```likeCount``` which is my field. And then replaced ```$array``` with ```$_likes``` which is my array of who liked the document – SKeney May 06 '20 at 16:25
  • I am not completely sure why your example didn't work in my case as it seems like it should. I posted what did work below using ```aggregate``` and ```forEach``` with ```BulkOp``` – SKeney May 06 '20 at 16:28
0

The query that ended up working for me:

var bulkOp = db.posts.initializeUnorderedBulkOp(); 
var count = 0;

db.posts.aggregate([
    { "$match": { 
        "_likes": { "$exists": true }
    }}, 
    { "$project": { "likeCount": { "$size": "$_likes" } } }
]).forEach(function(doc) { 
        bulkOp.find({ "_id": doc._id }).updateOne({ 
            "$set": { "likeCount": NumberInt(doc.likeCount) }
        });
        count++;
        if (count % 200 === 0) {
            // Execute per 200 operations and re-init
            bulkOp.execute();
            bulkOp = db.posts.initializeUnorderedBulkOp();
        }
})

// Clean up queues
if (count > 0) { 
    bulkOp.execute();
}
SKeney
  • 1,965
  • 2
  • 8
  • 30