MongoDb c# 驱动程序按字段值查找数组中的项目
MongoDb c# driver find item in array by field value
我发现检查方法是简单数组中包含的值:
var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");
但是如何通过一个具体的字段来查找具有多个字段的复杂项目呢?
我找到了使用 BsonDocument
生成器通过点符号方法编写它的方法,但是我如何使用类型化的 lambda 符号来完成它?
upd
我觉得有点
builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)
但现在无法检查,有人可以帮忙吗?
有ElemMatch
var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
您需要 $elemMatch
运算符。您可以使用 Builders<T>.Filter.ElemMatch
或 Any
表达式:
Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()
http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch
从C#驱动2.4.2版本开始,可以使用IFindFluent接口查询数组元素。 ElemMatch 不能直接用于字符串数组,而 find 接口可以用于简单或复杂类型(例如 'Tags.Name')并且是强类型的。
FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
...
await myCollection.FindAsync(tcFilter);
Linq 驱动程序使用聚合框架,但对于没有聚合运算符的查询,查找速度更快。
请注意,这在以前版本的驱动程序中已被破坏,因此在原始发布时没有答案。
这是一个示例,returns 来自数组的单个复杂项(使用 MongoDB.Driver v2.5.0):
简单数据模型
public class Zoo
{
public List<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
选项 1(聚合)
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
}
选项 2(过滤器和 Linq)这对我来说慢了大约 5 倍
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);
}
我发现检查方法是简单数组中包含的值:
var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");
但是如何通过一个具体的字段来查找具有多个字段的复杂项目呢?
我找到了使用 BsonDocument
生成器通过点符号方法编写它的方法,但是我如何使用类型化的 lambda 符号来完成它?
upd
我觉得有点
builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)
但现在无法检查,有人可以帮忙吗?
有ElemMatch
var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
您需要 $elemMatch
运算符。您可以使用 Builders<T>.Filter.ElemMatch
或 Any
表达式:
Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()
http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch
从C#驱动2.4.2版本开始,可以使用IFindFluent接口查询数组元素。 ElemMatch 不能直接用于字符串数组,而 find 接口可以用于简单或复杂类型(例如 'Tags.Name')并且是强类型的。
FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
...
await myCollection.FindAsync(tcFilter);
Linq 驱动程序使用聚合框架,但对于没有聚合运算符的查询,查找速度更快。
请注意,这在以前版本的驱动程序中已被破坏,因此在原始发布时没有答案。
这是一个示例,returns 来自数组的单个复杂项(使用 MongoDB.Driver v2.5.0):
简单数据模型
public class Zoo
{
public List<Animal> Animals { get; set; }
}
public class Animal
{
public string Name { get; set; }
}
选项 1(聚合)
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
}
选项 2(过滤器和 Linq)这对我来说慢了大约 5 倍
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);
}