MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

O driver Mongodb C # retorna apenas os subdocumentos correspondentes na matriz


Normalmente, você precisa usar $filter no Aggregation Framework para filtrar a matriz aninhada. No entanto, há uma maneira mais fácil de conseguir isso usando o MongoDB .NET Driver e o IQueryable interface.

Considerando o modelo mais simples:
public class MyModel
{
    public string _id { get; set; }
    public IEnumerable<MyNestedModel> myArray { get; set; }
}

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

e seguintes dados:
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);

você pode simplesmente chamar .AsQueryable() em sua coleção e, em seguida, você pode escrever a consulta LINQ que será traduzida pelo driver MongoDB para $filter , experimentar:
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();

EDITAR:

Alternativamente, você pode escrever $filter parte como uma string bruta e então use .Aggregate() método. Usando essa abordagem, você não precisa "mapear" todas as propriedades, mas a desvantagem é que você está perdendo a segurança de tipo, pois isso é apenas uma string, tente:
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 é usado aqui para substituir o campo existente.