How to filter an array within a Collection in MONGODB - C#

Asked

Viewed 329 times

4

I have the Collection PESSOA with a list of Languages as below:

            {
                "_id" : ObjectId("576be476ab76191bec2ff38c"),
                "Nome" : "Nome um",
                "Idiomas" : [ 
                    {
                        "idioma" : "pt-BR",
                        "descricao" : "Brasil"
                    }, 
                    {
                        "idioma" : "en-US",
                        "descricao" : "USA"
                    }, 
                    {
                        "idioma" : "en-EN",
                        "descricao" : "Espanha"
                    }
                ],
                "Idade" : 10
            }

I need to set which Languages item should be listed, I got this result in Mongoshell with the command below:

            db.getCollection('Pessoas').find({ "_id" : ObjectId("576be476ab76191bec2ff38c")}, 
                {
                    Nome:1,
                    'Idiomas': {$elemMatch: {'idioma': "en-US"}},
                    Idade:1
                })    

And I got the result:

            /* 1 */
            {
                "_id" : ObjectId("576be476ab76191bec2ff38c"),
                "Nome" : "Nome um",
                "Idiomas" : [ 
                    {
                        "idioma" : "en-US",
                        "descricao" : "USA"
                    }
                ],
                "Idade" : 10
            }

Any suggestions on how to do this in C#?

My current code. I have a _id list and need this list to return with the filtered language:

        List<ObjectId> ListaDeIds = new List<ObjectId>();

        ListaDeIds.Add(new ObjectId("576be476ab76191bec2ff38c"));
        ListaDeIds.Add(new ObjectId("576be47aab76191bec2ff38d"));
        ListaDeIds.Add(new ObjectId("576be47bab76191bec2ff38e"));

        var collection = db.GetCollection<Pessoa>(collectionName);
        var filter = Builders<Pessoa>.Filter.AnyIn("_id", ListaDeIds);

        return await collection.Find<Pessoa>(filter).ToListAsync();

1 answer

0

One of the ways to do this is to do the Unwind array. This is equivalent to doing a kind of SelectMany in Linq.

You will have a different object for each language and at that time you can filter the languages:

public class Pessoa{
    public string Nome{ get; set; }
    public int Idade { get; set; }
    public ICollection<IdiomaMongo> Idiomas{ get; set; }
}

public class PessoaIdioma{
    public string Nome{ get; set; }
    public int Idade { get; set; }
    public IdiomaMongo Idioma{ get; set; }
}

public class IdiomaMongo{
    public string Descricao{ get; set; }
    public string Idioma{ get; set; }
}

var db = _mongo.GetDatabase("mongoDatabase");
var personMongo = db.GetCollection<Idioma>("Pessoa");

personMongo
.Aggregate()
.Match(filter)
.Unwind<Pessoa, PessoaIdioma>(n => n.Idiomas, new AggregateUnwindOptions<PessoaIdioma>() {
    PreserveNullAndEmptyArrays = true
})
.Match(p => p.Idioma.Idioma == "en-US");

Browser other questions tagged

You are not signed in. Login or sign up in order to post.