c# - create - mongodb driver net core
MongoDb c#driver encuentra el elemento en una matriz por valor de campo (4)
A partir de la versión 2.4.2 de los controladores C #, la interfaz IFindFluent se puede utilizar para consultar en el elemento de matriz. ElemMatch no se puede usar directamente en una matriz de cadenas, mientras que la interfaz de búsqueda funcionará en tipos simples o complejos (por ejemplo, ''Tags.Name'') y está fuertemente tipada.
FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
...
await myCollection.FindAsync(tcFilter);
El controlador Linq usa el marco de agregación, pero para una consulta sin operadores de agregación, un hallazgo es más rápido.
Tenga en cuenta que esto se ha roto en versiones anteriores del controlador, por lo que la respuesta no estaba disponible en el momento de la publicación original.
Encontré que la forma de verificar es que el valor contiene en una matriz simple:
var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");
Pero, ¿cómo encontrar un elemento complejo con muchos campos por un campo concreto? Encontré la forma de escribirlo a través del enfoque de notación de puntos con BsonDocument
, pero ¿cómo puedo hacerlo con notaciones Lambda escritas?
actualizarse
creo que es una especie de
builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)
pero no puedo verificar ahora, ¿alguien podría ayudar?
Aquí hay un ejemplo que devuelve un solo elemento complejo de una matriz (usando MongoDB.Driver v2.5.0):
Modelo de datos simple
public class Zoo
{
public List<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
Opción 1 (Agregación)
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
}
Opción 2 (Filter & Linq) Esto fue 5 veces más lento para mí
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);
}
Hay ElemMatch
var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
Necesitas el operador $elemMatch
. Podría usar Builders<T>.Filter.ElemMatch
o una expresión Any
:
Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()
http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch