bynik
bynik

Reputation: 77

MongoDB .NET Driver - How to increment double nested field

The goal: to increment double nested field with the specific identifier in the entity.

mongo entity

The example of the document here:

competition_dota2

{
    "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "type" : "COMPETITION_TYPE_ESPORTDOTA2",
    "status_type" : "COMPETITION_STATUS_TYPE_WAITING",
    "start_time" : 
    {
        "seconds": "60",
         "nanos": 928852400
    },
    "coefficient_groups" : 
    [
        {
            "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
            "name" : "winner",
            "type" : "OUTCOME_GROUP_TYPE_ONE_WINNER",
            "coefficients" : 
            [
                    {
                        "id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
                        "description" : "team1 won",
                        "rate" : 1.2,
                        "status_type" : "COEFFICIENT_STATUS_TYPE_ACTIVE",
                        "amount" : 0,
                        "probability" : 50
                    },
                    {
                        "id" : "3c203bd7-2d7e-4937-a82a-e451cedf2ba8",
                        "description" : "team2 won",
                        "rate" : 0,
                        "status_type" : "COEFFICIENT_STATUS_TYPE_ACTIVE",
                        "amount" : 0,
                        "probability" : 50
                    }
            ]
        }
    ],
    "team1_id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "team2_id" : "b350c9fd-3632-4b0a-b5cb-66e41d530f55",
    "team1_kill_amount" : 0,
    "team2_kill_amount" : 0,
    "total_time" : 
    {
        "seconds": "60",
         "nanos": 928852400
    }
}

I'm trying to increment the "Amount" field.
For that, I'm using specific identifiers for both nested fields.
Is it enough to create find option for the top model only?

var competitionIdstring = competitionId.ToString();
var сoefficientIdstring = сoefficientId.ToString();

var filterBuilder = Builders<CompetitionDota2Entity>.Filter;
var updateBuilder = Builders<CompetitionDota2Entity>.Update;

var filterCompetitionId = filterBuilder.Eq(x => x.Id, competitionId.ToString());

var update = Builders<CompetitionDota2Entity>.Update;
var incAmount = update.Inc(
    "CompetitionDota2Entity.CoefficientGroups.$.Coefficients.$.Amount",
    amount);

var existingCoefficientGroup = await _collection.FindOneAndUpdateAsync(
                    filterCompetitionId,
                    incAmount,
                    _defaultCompetitionDota2EntityFindOption,
                    token);

Upvotes: 1

Views: 211

Answers (1)

Yong Shun
Yong Shun

Reputation: 51295

You need to works with the update with $[<identifier>] filtered positional operator in order to update the element in the nested arrays.

With MongoDB .NET Driver v2.16 and above

In MongoDB .NET Driver v2.16 release, it offers the feature of Implement positional update operators in LINQ3.

Pre-requisites:

Enable LinqProvider.V3 in MongoClientSettings.

MongoClientSettings settings = MongoClientSettings.FromConnectionString(
    mongoUri
);
settings.LinqProvider = MongoDB.Driver.Linq.LinqProvider.V3;
var update = Builders<CompetitionDota2Entity>.Update;
var incAmount = update.Inc(x => x.CoefficientGroups.AllMatchingElements("cg")
    .Coefficients.AllMatchingElements("c").Amount,
    amount);

FindOneAndUpdateOptions<CompetitionDota2Entity> _defaultCompetitionDota2EntityFindOption = new FindOneAndUpdateOptions<CompetitionDota2Entity>
{
    ArrayFilters = new ArrayFilterDefinition[]
    {
        new BsonDocumentArrayFilterDefinition<CoefficientGroup>
        (
            new BsonDocument("cg._id", competitionIdstring)
        ),
        new BsonDocumentArrayFilterDefinition<Coefficient> 
        (
            new BsonDocument("c._id", сoefficientIdstring)
        )
    }
};

var existingCoefficientGroup = await _collection.FindOneAndUpdateAsync(
                    filterCompetitionId,
                    incAmount,
                    _defaultCompetitionDota2EntityFindOption,
                    token);

With MongoDB .NET Driver v2.16 before

var incAmount = update.Inc(
    "coefficient_groups.$[cg].coefficients.$[c].amount",
    amount);

FindOneAndUpdateOptions<CompetitionDota2Entity> _defaultCompetitionDota2EntityFindOption = new FindOneAndUpdateOptions<CompetitionDota2Entity>
{
    ArrayFilters = new ArrayFilterDefinition[]
    {
        new BsonDocumentArrayFilterDefinition<CoefficientGroup>
        (
            new BsonDocument("cg._id", competitionIdstring)
        ),
        new BsonDocumentArrayFilterDefinition<Coefficient> 
        (
            new BsonDocument("c._id", сoefficientIdstring)
        )
    }
};

Demo

enter image description here

Upvotes: 1

Related Questions