[CSHARP-1909] Using indexOf(-1) for Positional Operator does not work in bulk operations Created: 08/Feb/17  Updated: 14/Dec/18  Resolved: 14/Dec/18

Status: Closed
Project: C# Driver
Component/s: Linq
Affects Version/s: 2.4.2
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Kalarrs Topham Assignee: Dmitry Lukyanov (Inactive)
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible

 Description   

When attempting to use indexOf(-1) in a bulk operation update, the produced mongo query does not contain the "$" positional operator resulting in the query throwing an error.

Example

bulk.Find(Query<Users>.Where(user => user.FavoriteColors.Any(f => f.Name == "green")))
.UpdateOne(Update<Users>.Set(user => user.FavoriteColors.IndexOf(-1).Name, "blue");

Results in {$set:

{"user.favoriteColors.-1.name":"blue"}

which throws and error.

Workaround

bulk.Find(Query<Users>.Where(user => user.FavoriteColors.Any(f => f.Name == "green")))
.UpdateOne(Update.Set("user.favoriteColors.$.name", "blue");

NOTE: It would be nice if indexOf(-1) could be supported across ALL query builders, including legacy, current, and .net core.

References:
https://jira.mongodb.org/browse/CSHARP-531
https://github.com/mongodb/mongo-csharp-driver/blob/master/tests/MongoDB.Driver.Legacy.Tests/Operations/BulkWriteOperationTests.cs



 Comments   
Comment by Dmitry Lukyanov (Inactive) [ 13/Dec/18 ]

Dear exocom,

thank you for your participation. 

I've checked the ticket description as well as your pull request. I noticed that you use the builders (Query and Update) from the legacy driver. As we have a new, more fully-featured implementation of LINQ based on the aggregation framework, we are no longer making enhancements to the legacy implementation when there are available approaches that will solve the problem. The recommended way to accomplish your target is by using the builders in the following way :

users.UpdateOne(
    Builders<Users>.Filter.Where(user => user.FavoriteColors.Any(f => f.Name == "green")), 
    Builders<Users>.Update.Set(user => user.FavoriteColors.ElementAt(-1).Name, "blue"));

You can also use array brackets "[-1]" instead of ElementAt to reach the same result.

The rendered result query from Update builder will be :

{ "$set" : { "FavoriteColors.$.Name" : "blue" } }

Please let me know if you still have questions.

 

Comment by Kalarrs Topham [ 10/Feb/17 ]

Updated the LINQ code and added a unit test. See pull request on githhub. #269
https://github.com/mongodb/mongo-csharp-driver/pull/269

Generated at Wed Feb 07 21:41:02 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.