[GODRIVER-1823] I need a updateAndReturnResult that is atomic Created: 07/Jan/21 Updated: 27/Oct/23 Resolved: 19/Jan/21 |
|
| Status: | Closed |
| Project: | Go Driver |
| Component/s: | API |
| Affects Version/s: | 1.4.4 |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | Andrew Hodel | Assignee: | Kevin Albertson |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Linux |
||
| Description |
|
Currently I am needing to do this:
2148 // start host modification atomicity 2149 // that is required because the host outsideIp may be updated twice once before the change and once after 2150 // yet before the read for checking if the IP changed 2151 2152 updateResult, err := collection.UpdateOne(context.TODO(), filter, update) 2153 if err != nil { 2154 _ = updateResult 2155 fmt.Printf("\n\nerror in wss config request when updating host: %s\n", err) 2156 }2157 2158 //fmt.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount) 2159 2160 // compare this_host.OutsideIp and the update result.outsideIp to see if a new entry was added 2161 // if an entry was added, increment the host document's outsideIpChangesPerDay field 2162 var updated_host Host 2163 err = collection.FindOne(context.TODO(), filter).Decode(&updated_host) 2164 2165 fmt.Printf("this_host.outsideIp: \t%+v\nupdated_host.outsideIp: \t%v\n\n", this_host.OutsideIp, updated_host.OutsideIp); 2166 2167 if (updated_host.OutsideIp[0] != this_host.OutsideIp[0]) { 2168 2169 // increment outsideIpChangesPerDay 2170 2171 }2172 2173 // end host modification atomicity
If line 2152 (collection.UpdateOne) returned the updated document with regards to not allowing another update before returning (ie atomic) then I would not have to start and end atomicity on the routine...
Thanks. |
| Comments |
| Comment by Andrew Hodel [ 20/Jan/21 ] |
|
This is difficult to find in the documentation.
Here's how you actually write it:
<code> var updated_host Host after := options.After opt := options.FindOneAndUpdateOptions { ReturnDocument: &after, }updateFindErr := collection.FindOneAndUpdate(context.TODO(), filter, update, &opt).Decode(&updated_host) if (updateFindErr != nil) { fmt.Printf("error with FindOneAndUpdate: %s\n", updateFindErr) }</code>
Here are the 5 urls of documentation and examples you have to read to understand it because it is not written out in the documentation for FindOneAndUpdate()
https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo#Collection.FindOneAndUpdate https://pkg.go.dev/go.mongodb.org/mongo-driver@v1.4.5/mongo/options#FindOneAndUpdateOptions https://pkg.go.dev/go.mongodb.org/mongo-driver@v1.4.5/mongo/options#ReturnDocument https://github.com/mongodb/mongo-go-driver/blob/v1.4.5/mongo/options/mongooptions.go#L83 https://github.com/cgiacomi/go-mongo-examples/blob/master/main.go
|
| Comment by Kevin Albertson [ 19/Jan/21 ] |
|
Hello andrewhodel@gmail.com! If I am understanding correctly, you need an atomic find and update to ensure no changes occur between the UpdateOne and FindOne operations in the example provided. The findOneAndUpdate may suffice. It uses the underlying findAndModify command, which has atomicity guarantees when operating on one document (reference). It can optionally return the document before or after the update based on the ReturnDocument option. Since this isn't a bug or feature request we're closing the issue. For further assistance please create a post in our community forum here Sincerely, |