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
The problem is that in the
$replaceAll
operation thefind
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 updatableStep
field, and replace that.But
$regexpFind
doesn’t return the matching substring, it returns an object whosematch
field contains the matching substring. To get itsmatch
field, you may use$getField
.This is how it may look like (only the
"then"
branch, the rest is unchanged and omitted for brevity):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.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.