skip to Main Content

I have a collection with docs like:

{ID: xxx, firstCreateDate: xxx, isActive: false}
  1. I want to find all the docs where isActive = false, then update isActive to true, and also update firstCreateDate to current date if not set before. I’m not sure how to conditionally update filed firstCreateDate. Couldn’t get the conditionally update working right now. Got
    firstCreateDate = {$cond:[{"firstCreateDate":{"$exists":false}}, "$firstCreateDate", newdata]}
  2. I also want to use a custom function to generate a new field internalID based on original ID field. I tried to use UpdateMany(), but seems like there is no way to get the value and calculate the new value using your own function. I’m thinking about use Find() to find all docs, then decode it, and then update docs one by one based on id. Is there any better solution for this?

This is what I have now:

filter := bson.M{"isActive": false}
update := bson.M{"set": bson.M{"isActive": true, "firstCreateDate": bson.M{
  "$cond": bson.A{
    bson.M{"firstCreateDate", bson.M{"$exists", false}},
    "$firstCreateDate",
    newDate,
  }
}}}

collection.UpdateByID(
  context.Background(),
  id,
  update,
)

I’m using mongo-driver lib, anyone can help

2

Answers


  1. A few things..

    1. If you use the _id default it will be generated for you and you can extract the creation date directly from there. This is mainly a preference question honestly whether you want to see a clear date in your document for readability or just grab what exists in the generated _id.
    2. I have not had to solve for the second requirement before. Personally, I would never generate ObjectIds in sub documents unless they were a foreign key to another collection. If that was the case, I would generate the ObjectID in the the other collection first and then associate that _id with this collection by inserting the reference.
    3. You can use the aggregation pipeline in updateMany statements. $set takes mostly the same syntax as the projection operator.

    Here is the updateMany that will solve your first question. It uses the mongosh syntax but you should be able to convert the logic to go.

    db.collection.updateMany(
        { isActive: false }, 
        [{$set: {
            firstCreateDate: {
                $ifNull: [
                    '$firstCreateDate',
                    ISODate('2022-03-26T03:52:45.240Z')
                ]
            },
            isActive: {
                $toBool: true
            },
            _idExtractDate: {
                $convert: {
                    input: '$_id',
                    to: 'date'
                }
            }
        }}]
    );
    
    Login or Signup to reply.
  2. I can help you with the first part.

    First you just want to find where isActive is false and where firstCreateDate is not set. If the field exist and is just Null, take a look at https://www.mongodb.com/docs/manual/reference/operator/aggregation/ifNull/

    res, err := collection.UpdateMany(ctx, bson.M{
        "isActive": false,
        "firstCreateDate": bson.M{"$exists": false},
    }, bson.D{
        {"$set", bson.M{"isActive": true}},
        {"$set", bson.M{"firstCreateDate": newDate}},
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search