Hello all !
Not sure about the right place to post my problem, but I’m pretty nooby in Mongo DB, and didn’t found how to repport Issues (sorry)…
Working on a project with MongoDb, I’m facing an issue while using Projection in my Aggregation.
I have the following piece of code in my function, which is supposed to Project some data :
var query = RepositoryCollection.Aggregate()
.Project(p => new QueryProductWithSingleMovement
{
Id = p.Id,
CreationDate = p.CreationDate,
CreationOperatorId = p.CreationOperatorId,
CreationSiteId = p.CreationSiteId,
DestructionDate = p.DestructionDate,
ProductNumber = p.ProductNumber,
ProductNumberId = p.ProductNumberId,
ProductNumberReleaseVersion = p.ProductNumberReleaseVersion,
SerialNumber = p.SerialNumber,
Movement = p.Movements.First(m => m.Id == p.LastMovementId)
});
var result = await query.ToListAsync();
So here the MongoSH query that is supposed to be generated should look like :
db.myCollection.aggregate([
{
"$project": {
"Id": "$_id",
"CreationDate": "$creationDate",
"CreationOperatorId": "$creationOperatorId",
"CreationSiteId": "$creationSiteId",
"DestructionDate": "$destructionDate",
"ProductNumber": "$pnNumber",
"ProductNumberId": "$pnId",
"ProductNumberReleaseVersion": "$pnReleaseVersion",
"SerialNumber": "$serialNumber",
"Movement": {
"$arrayElemAt": [
{
"$filter": {
"input": "$movements",
"as": "m",
"cond": {
"$eq": [
"$$m._id",
"$lastMovementId"
]
}
}
},
0
]
},
"_id": 0
}
}
])
But instead I get the following result :
db.myCollection.aggregate([
{
"$project": {
"Id": "$_id",
"CreationDate": "$creationDate",
"CreationOperatorId": "$creationOperatorId",
"CreationSiteId": "$creationSiteId",
"DestructionDate": "$destructionDate",
"ProductNumber": "$pnNumber",
"ProductNumberId": "$pnId",
"ProductNumberReleaseVersion": "$pnReleaseVersion",
"SerialNumber": "$serialNumber",
"Movement": {
"$arrayElemAt": [
{
"$filter": {
"input": "$movements",
"as": "m",
"cond": {
"$eq": [
"$$m._id",
"$$m.lastMovementId"
]
}
}
},
0
]
},
"_id": 0
}
}
])
The difference is quite tricky to find out but it is located inside the “Movement” property in the “$filter” condition. Actually in the “$eq” expression we are supposed to compatre the Movement._id value with the Product.LastMovementId value (which are both ObjectId), but instead having
"$eq": [
$$m._id",
$lastMovementId"
]
we have
"$eq": [
$$m._id",
$$m.lastMovementId"
]
For more clarty, here are my models :
Product.cs
public class ProductItemBase
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public ObjectId Id { get; set; } = default!;
/// <summary>
/// Gets or sets the product number identifier.
/// </summary>
[BsonElement("pnId")]
public int ProductNumberId { get; set; }
/// <summary>
/// Gets or sets the product number Number value.
/// </summary>
[BsonElement("pnNumber")]
public string ProductNumber { get; set; } = default!;
/// <summary>
/// Gets or sets the creation date.
/// </summary>
[BsonElement("creationDate")]
public DateTime CreationDate { get; set; }
/// <summary>
/// Gets or sets the creation site identifier.
/// </summary>
[BsonElement("creationSiteId")]
public int CreationSiteId { get; set; }
/// <summary>
/// Gets or sets the creation operator identifier.
/// </summary>
[BsonElement("creationOperatorId")]
public int CreationOperatorId { get; set; }
/// <summary>
/// Gets or sets the product number release version.
/// </summary>
[BsonElement("pnReleaseVersion")]
public string ProductNumberReleaseVersion { get; set; } = default!;
/// <summary>
/// Gets or sets the serial number.
/// </summary>
[BsonElement("serialNumber")]
public string SerialNumber { get; set; } = default!;
/// <summary>
/// Gets or sets the destruction date.
/// </summary>
[BsonElement("destructionDate")]
public DateTime? DestructionDate { get; set; }
/// <summary>
/// Gets or sets the last movement identifier.
/// </summary>
[BsonElement("lastMovementId")]
public ObjectId LastMovementId { get; set; }
/// <summary>
/// Gets or sets the last movement identifier.
/// </summary>
[BsonElement("lastOperationId")]
public ObjectId? LastOperationtId { get; set; }
/// <summary>
/// Gets or sets the movements.
/// </summary>
[BsonElement("movements")]
public List<MovementItem>? Movements { get; set; }
}
Movement.cs
public class MovementItem : CollectionItemBase
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public ObjectId Id { get; set; } = default!;
/// <summary>
/// Gets or sets the product identifier.
/// </summary>
[BsonElement("productId")]
public ObjectId? ProductId { get; set; }
/// <summary>
/// Gets or sets the type of the movement.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))] // JSON.Net
[BsonRepresentation(BsonType.String)] // Mongo
[BsonElement("movementType")]
public MovementType MovementType { get; set; }
/// <summary>
/// Gets or sets the movement date.
/// </summary>
[BsonElement("movementDate")]
public DateTime MovementDate { get; set; }
}
So if anyone of you have ever met this issue, or can tell me how to report it (if it is not the right place), I’ll appreciate it a lot .