skip to Main Content

I’m trying to append the text "[retrying: " + time.Now().Format("15:04") + "]" in such a way that if it is missing in the field, it will be added; if it is present, it will be replaced.

For example (adding text):

{
  "_id": {
    "$oid": "66f134e7ad3dc5c40ced7b2a"
  },
  "CreatedAt": {
    "$date": "2024-09-23T09:29:11.276Z"
  },
  "UpdatedAt": {
    "$date": "2024-09-24T22:15:50.679Z"
  },
  "Step": "Waiting to receive information from the network"
}

Target:

{
  "_id": {
    "$oid": "66f134e7ad3dc5c40ced7b2a"
  },
  "CreatedAt": {
    "$date": "2024-09-23T09:29:11.276Z"
  },
  "UpdatedAt": {
    "$date": "2024-09-24T22:15:50.679Z"
  },
  "Step": "Waiting to receive information from the network [retrying 12:00]"
}

Or (replacing text)

{
  "_id": {
    "$oid": "66f134e7ad3dc5c40ced7b2a"
  },
  "CreatedAt": {
    "$date": "2024-09-23T09:29:11.276Z"
  },
  "UpdatedAt": {
    "$date": "2024-09-24T22:15:50.679Z"
  },
  "Step": "Waiting to receive information from the network [retrying 12:00]"
}

Target:

{
  "_id": {
    "$oid": "66f134e7ad3dc5c40ced7b2a"
  },
  "CreatedAt": {
    "$date": "2024-09-23T09:29:11.276Z"
  },
  "UpdatedAt": {
    "$date": "2024-09-24T22:15:50.679Z"
  },
  "Step": "Waiting to receive information from the network [retrying 12:05]"
}

Currently I have this code that I am trying with:

fieldName := "$Step" 
retryingRegex := `s[retrying:.*]`
retryingInfo := " [retrying: " + time.Now().Format("15:04") + "]"
update := bson.A{
    bson.M{
        "$set": bson.M{
            "Step": bson.M{
                "$cond": bson.M{
                    "if": bson.M{
                        "$regexMatch": bson.M{
                            "input": fieldName,
                            "regex": retryingRegex,
                        },
                    },
                    "then": bson.M{
                        "$replaceAll": bson.M{
                            "input":       fieldName,
                            "find":        retryingRegex,
                            "replacement": retryingInfo,
                        },
                    },
                    "else": bson.M{
                        "$concat": []string{
                            fieldName,
                            retryingInfo,
                        },
                    },
                },
            },
        },
    },
}
filter := bson.M{"_id": id}
collection.UpdateOne(ctx, filter, update)

But it doesn’t seems to work.
DB version v7.0.8
Go version 1.22

2

Answers


  1. The problem is that in the $replaceAll operation the find field must be a "plain" string to find (and replace). It can’t be a regular expression (more precisely it’s not used as a regular expression).

    What you may do is execute a $regexFind to find the part that occurs in the value of the updatable Step field, and replace that.

    But $regexpFind doesn’t return the matching substring, it returns an object whose match field contains the matching substring. To get its match field, you may use $getField.

    This is how it may look like (only the "then" branch, the rest is unchanged and omitted for brevity):

    "then": bson.M{
        "$replaceAll": bson.M{
            "input": fieldName,
            "find": bson.M{
                "$getField": bson.M{
                    "field": "match",
                    "input": bson.M{
                        "$regexFind": bson.M{
                            "input": fieldName,
                            "regex": retryingRegex,
                        },
                    },
                },
            },
            "replacement": retryingInfo,
        },
    },
    

    Note that personally I would just store retryingInfo in a separate field, which would result in much simpler and cleaner code. Even that formatting is unnecessary, just store the timestamp, and it can be formatted when displayed to the user.

    Login or Signup to reply.
  2. To handle your situation where you need to update a field by either appending or replacing a specific text ([retrying: " + time.Now().Format("15:04") + "]), you need to adjust your MongoDB query in Go. Specifically, MongoDB’s $replaceAll operation does not accept regular expressions as a find string, so you must work around that limitation.

    Here’s an approach using $regexFind and $getField in MongoDB, which allows you to locate the matched part of the string and then replace it.
    Explanation:
    $regexFind: This finds the part of the Step field that matches the regular expression [retrying:.*].
    $getField: This extracts the matched substring from the result of $regexFind using the match field.
    $replaceAll: This replaces the matched substring with the new retryingInfo.
    $cond: If the retrying string is already present, it replaces it; otherwise, it appends the string to the Step field.
    Debugging Tips:
    Ensure you are checking the MatchedCount and ModifiedCount in the UpdateOne result to confirm whether the query is correctly matching and modifying documents.
    If you see no modification, double-check that the Step field has the correct format and the regex works as expected.
    This should now work for both replacing and appending [retrying: time] depending on the condition.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search