gds03
gds03

Reputation: 1379

MongoDB C# Driver - Where Last SubDocument Field Eq to 'X'

I am using MongoDB as my DB storage and the query adaption has being nice from SQL to Mongo although I am not understanding quite well how can I achieve simple queries like:

Example:

{
    Name: '',
    Addresses:
    [
        {
            Street: '',
            IsDefault: true/false       
        },
        {
            Street: '',
            IsDefault: true/false       
        },
        {
            Street: '',
            IsDefault: true/false       
        }
    ]       
}

The result should be:

All the persons that have the last Address 'IsDefault' field is set to true, and only those.

I've searched online but it seems hard to find a way to figure this out.

Appreciated if someone can give me an hint.

Thanks

Upvotes: 1

Views: 177

Answers (2)

Dĵ ΝιΓΞΗΛψΚ
Dĵ ΝιΓΞΗΛψΚ

Reputation: 5669

you don't really need the addFields stage. just run a match stage like this:

db.Markets.aggregate(
[
    {
        $match: {
            $expr: {
                $eq: [{ $last: "$Positions.ExitCompleted" }, true]
            }
        }
    }
])

unfortunately there's no strongly-typed way afaik to translate the above to a c# driver query.

have a look at this article for an alternative way to run advanced queries like these.

Upvotes: 1

gds03
gds03

Reputation: 1379

Well,

I have done some research after and a mix of results pointed me to a direction.

I am using MongoDB Compass, so I have built the aggregation there and extracted to C#. This can be done using: Compass > (above tabs - Aggregation). Then you select your stages. I have the following stages:

[{$addFields: {
  lastExitCompleted: {
    $last: '$Positions.ExitCompleted'
  }
}}, {$match: {
  lastExitCompleted: true
}}]

then I have exported to C# (however you can export to the available languages Compass supports) using the "Export pipeline to language" button.

After that my C# aggregation code is the following:

var addFieldsExpr = new BsonDocument("$addFields",
                new BsonDocument("lastFieldValue",
                new BsonDocument("$last", $"${nameof(MarketInfo.Positions)}.{nameof(MarketInfoPosition.ExitCompleted)}"))
            );

            var matchExpr = new BsonDocument("$match",
                new BsonDocument("lastExitCompleted", exitCompleted) // exitCompleted is bool.
            );

            var markets = await (await db.Markets
                .AggregateAsync(
                    PipelineDefinition<MarketInfo, MarketInfo>
                        .Create(addFieldsExpr, matchExpr) <-- this is what makes the job.
                ))
                .ToListAsync();

            return markets;

We can use nameof to avoid typos in the expressions, since we don't have strongly typed expressions.

I have searched and it seems that C# Driver do not supports $addFields, but please if I am wrong give a shout.

Upvotes: 0

Related Questions