So let's start from the drawing board and get some data in via the mongo console:
db.models.insertMany([
{
_id : 1,
ModelType: "Player",
ModelList: [
{ ModelHashKey: "1", ModelName: "1", ModelAttribute: "Male" },
{ ModelHashKey: "2", ModelName: "2", ModelAttribute: "Male" },
{ ModelHashKey: "3", ModelName: "3", ModelAttribute: "Female" }
]
},
{
_id : 2,
ModelType: "NotPlayer",
ModelList: [
{ ModelHashKey: "4", ModelName: "4", ModelAttribute: "Male" },
{ ModelHashKey: "5", ModelName: "5", ModelAttribute: "Male" },
{ ModelHashKey: "6", ModelName: "6", ModelAttribute: "Female" }
]
}
]);
from the question I'm assuming you want to only select the document with the _id of 1 and also filter the list of ModelLiet to the 2 Males (1, 2).
So let's start by filting down the documents, this can be done by a simple find:
db.models.find({"ModelType": "Player", "ModelList.ModelAttribute": "Male"}).pretty()
Note that we can add an index of {"ModelType" : 1, "ModelList.ModelAttribute": 1 } to also support this query.
However, if we execute this find we'll get the whole document back:
{
"_id" : 1,
"ModelType" : "Player",
"ModelList" : [
{
"ModelHashKey" : "1",
"ModelName" : "1",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "2",
"ModelName" : "2",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "3",
"ModelName" : "3",
"ModelAttribute" : "Female"
}
]
}
So here we want to flip this into an aggregation query and project the data with a filter.
db.models.aggregate([
{ $match: {"ModelType": "Player", "ModelList.ModelAttribute": "Male" } },
{ $addFields: { "ModelList" : {
$filter: {
input: "$ModelList",
as: "item",
cond: { $eq: [ "$$item.ModelAttribute", "Male" ] }
}
}
}
}
]);
If we execute the above we get the expected results back (try it here - https://mongoplayground.net/p/j6bP9TE6aTD):
{
"_id" : 1,
"ModelType" : "Player",
"ModelList" : [
{
"ModelHashKey" : "1",
"ModelName" : "1",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "2",
"ModelName" : "2",
"ModelAttribute" : "Male"
}
]
}
So let's covert this to C# using the MongoDB Driver, it's all fairly similar just bit different syntax:
public class Models
{
public int _id { get; set; }
public string ModelType { get; set; }
public List<ModelList> ModelList { get; set; } = new List<ModelList>();
}
public class ModelList
{
public string ModelHashKey { get; set; }
public string ModelName { get; set; }
public string ModelAttribute { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<Models>("models");
var models = collection.Aggregate()
.Match(Builders<Models>.Filter.Eq(x => x.ModelType, "Player") & Builders<Models>.Filter.ElemMatch(x => x.ModelList, Builders<ModelList>.Filter.Eq(x => x.ModelAttribute, "Male")))
.AppendStage<Models>(BsonDocument.Parse(@"{ $addFields: { ""ModelList"" : { $filter: { input: ""$ModelList"", as: ""item"", cond: { $eq: [""$$item.ModelAttribute"", ""Male""] } } } } }"))
.ToList();
foreach (var model in models)
{
foreach (var item in model.ModelList)
{
Console.WriteLine(item.ToJson());
}
}
}
}
Notice that we're using AppendStage<> as the C# driver doesn't support this aggregation stage natively yet.
Now if we run this C# code we'll get the following results:
{ "ModelHashKey" : "1", "ModelName" : "1", "ModelAttribute" : "Male" }
{ "ModelHashKey" : "2", "ModelName" : "2", "ModelAttribute" : "Male" }