MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Le pilote Mongodb C # renvoie uniquement les sous-documents correspondants dans le tableau

En règle générale, vous devez utiliser $filter dans Aggregation Framework pour filtrer le tableau imbriqué. Cependant, il existe un moyen plus simple d'y parvenir en utilisant MongoDB .NET Driver et IQueryable interface.

Considérant le modèle le plus simple :

public class MyModel
{
    public string _id { get; set; }
    public IEnumerable<MyNestedModel> myArray { get; set; }
}

public class MyNestedModel
{
    public string other { get; set; }
}

et les données suivantes :

var m = new MyModel()
{
    _id = "1",
    myArray = new List<MyNestedModel>() {
        new MyNestedModel() {  other = "stuff" },
        new MyNestedModel() { other = "stuff" },
        new MyNestedModel() { other = "stuff2" } }
};

Col.InsertOne(m);

vous pouvez simplement appeler .AsQueryable() sur votre collection, puis vous pouvez écrire une requête LINQ qui sera traduite par le pilote MongoDB en $filter , essayez :

var query = from doc in Col.AsQueryable()
            where doc._id == "1"
            select new MyModel()
            {
                _id = doc._id,
                myArray = doc.myArray.Where(x => x.other == "stuff")
            };

var result = query.ToList();

MODIFIER :

Sinon, vous pouvez écrire $filter part comme une chaîne brute, puis utilisez .Aggregate() méthode. En utilisant cette approche, vous n'avez pas besoin de "mapper" toutes les propriétés, mais l'inconvénient est que vous perdez la sécurité du type car il ne s'agit que d'une chaîne, essayez :

var addFields = BsonDocument.Parse("{ \"$addFields\": { myArray: { $filter: { input: \"$myArray\", as: \"m\", cond: { $eq: [ \"$$m.other\", \"stuff\" ] } }  } } }");

var query = Col.Aggregate()
               .Match(x => x._id == "1")
               .AppendStage<MyModel>(addFields);

$addFields est utilisé ici pour écraser le champ existant.