Search code examples
mongodbmongodb-.net-driver

How do I retrieve a document along with just one of its child documents in C#?


I have the following document in mongo

{"_id":{"$oid":"5e7b6cb9606503483494c63a"},"ProductId":{"$binary":{"base64":"V9+9bOaj8kyWrPwdAm0rBQ==","subType":"03"}},"ProductName":"TestProduct1","ProductItems":[{"_t":"ProductItem","ProductId":{"$binary":{"base64":"V9+9bOaj8kyWrPwdAm0rBQ==","subType":"03"}},"Code":"TP1A"},
{"_t":"ProductItem","ProductId":{"$binary":{"base64":"V9+9bOaj8kyWrPwdAm0rDE==","subType":"03"}},"Code":"TP1B"}]}

What I want to do is return by a query on ProductItem.Code that returns a product with the single matching child item. So preserving the object structure but eliminating all but the single matching child.

I have tried

Product prod = new Product();
IMongoCollection<Product> products = _database.GetCollection<Product>("Products");
var filter = Builders<Product>.Filter.ElemMatch(x=>x.ProductItems, x=>x.Code==code);
prod = products.Find(filter).FirstOrDefault();
return prod;

but this just ends up returning the root document and all of the children instead of just the root document and the single child that I searched for.


Solution

  • You can project the matched document in the array with the positional operator. This is [-1] in C# (https://docs.mongodb.com/manual/reference/operator/projection/positional/)

    var filter = Builders<Product>.Filter.ElemMatch(x=>x.ProductItems, x=>x.Code==code);
    var projection = Builders< Product >.Projection.Include(x => x.ProjectItems[-1])
    
    var found = await collection.Find(filter, projection).ToListAsync();
    var matchedProductItem =  found[0].ProductItems.First();