i found the way to check is the value contains in simple array :
var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");
But how to find a complex item with many fields by a concrete field ? I found the way to write it via the dot notation approach with BsonDocument
builder, but how can i do it with typed lambda notations ?
upd
i think it some kind of
builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)
but can't check right now, is anyone could help ?
There is ElemMatch
var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
You need the $elemMatch
operator. You could use Builders<T>.Filter.ElemMatch
or an Any
expression:
Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()
http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch
Here's an example that returns a single complex item from an array (using MongoDB.Driver v2.5.0):
Simple Data Model
public class Zoo
{
public List<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
Option 1 (Aggregation)
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) This was about 5x slower for me
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);
}
As of the 2.4.2 release of the C# drivers, the IFindFluent interface can be used for querying on array element. ElemMatch cannot be used on an array of strings directly, whereas the find interface will work on either simple or complex types (eg 'Tags.Name') and is strongly typed.
FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
...
await myCollection.FindAsync(tcFilter);
Linq driver uses the aggregation framework, but for a query with no aggregation operators a find is faster.
Note that this has been broken in previous versions of the driver so the answer was not available at the time of original posting.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.