j'ai trouvé le moyen de vérifier si la valeur contient dans un tableau simple:
var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");
Mais comment trouver un élément complexe avec plusieurs champs par un champ concret? J'ai trouvé le moyen de l'écrire via l'approche de la notation par points avec le générateur BsonDocument
, mais comment puis-je le faire avec des notations lambda typées?
mise à jour
je pense que c'est une sorte de
builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)
mais je ne peux pas vérifier en ce moment, est-ce que quelqu'un pourrait aider?
Il y a ElemMatch
var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
Vous avez besoin du $elemMatch
opérateur. Vous pouvez utiliser Builders<T>.Filter.ElemMatch
ou une expression Any
:
Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()
http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch
Voici un exemple qui renvoie un seul élément complexe à partir d'un tableau (à l'aide de MongoDB.Driver v2.5.0):
modèle de données simple
public class Zoo
{
public List<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
Option 1 (agrégation)
public Animal FindAnimalInZoo(string animalName)
{
var zooWithAnimalFilter = Builders<Zoo>.Filter
.ElemMatch(z => z.Animals, a => a.Name == animalName);
return _db.GetCollection<Zoo>("zoos").Aggregate()
.Match(zooWithAnimalFilter)
.Project<Animal>(
Builders<Zoo>.Projection.Expression<Animal>(z =>
z.Animals.FirstOrDefault(a => a.Name == animalName)))
.FirstOrDefault(); // or .ToList() to return multiple
}
Option 2 (Filter & Linq) C'était environ 5 fois plus lent pour moi
public Animal FindAnimalInZoo(string animalName)
{
// Same as above
var zooWithAnimalFilter = Builders<Zoo>.Filter
.ElemMatch(z => z.Animals, a => a.Name == animalName);
var zooWithAnimal = _db.GetCollection<Zoo>("zoos")
.Find(zooWithAnimalFilter)
.FirstOrDefault();
return zooWithAnimal.Animals.FirstOrDefault(a => a.Name == animalName);
}
Depuis la version 2.4.2 des pilotes C #, l'interface IFindFluent peut être utilisée pour interroger l'élément de tableau. ElemMatch ne peut pas être utilisé directement sur un tableau de chaînes, alors que l'interface de recherche fonctionnera sur des types simples ou complexes (par exemple 'Tags.Name') et est fortement typée.
FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
...
await myCollection.FindAsync(tcFilter);
Le pilote Linq utilise le cadre d'agrégation, mais pour une requête sans opérateur d'agrégation, la recherche est plus rapide.
Notez que cela a été brisé dans les versions précédentes du pilote de sorte que la réponse n'était pas disponible au moment de la publication d'origine.