如何使用MongoDB C#驱动实现嵌套数组uid匹配指定字符串数组的in查询
MongoDB C# 驱动嵌套数组字段批量IN查询解决方案
问题背景
存储的文档对象结构如下:
public class Foo { public string Id { get; set; } public List<FooBar> Bars { get; set; } // ... } public class FooBar { public string uid { get; set; } // ... }
现有查询条件数组:
var ArrayOfUid = new[] {"STK-00112","STK-00117","STK-00113","STK-00114"};
需求:查询所有满足嵌套对象FooBar.uid在ArrayOfUid范围内的文档,返回去重的产品列表。
已知MongoDB原生查询可正常执行:
db.collection.find({ "foobar.uid": { $in: ["STK-00113","STK-00117","STK-00113","STK-00114"] } })
目前单uid查询可正常运行:
var findFluent = collection.Find(Builders<Foo>.Filter.ElemMatch( foo => foo.Bars, foobar => foobar.uid == "STK-00113"));
但使用BsonDocument构造的批量查询返回空结果:
public List<Produit> GetFromSitesAsync(List<string> productSites) { // 运行无报错但返回空结果 FilterDefinition<Produit> filter = new BsonDocument( "foobar.uid", new BsonDocument( "$in", BsonArray.Create(productSites) ) ); return _produits.Find(filter).ToList(); }
解决方案
推荐使用强类型Filter构造方式,避免手动写字段名导致的拼写错误、属性映射不匹配问题:
public List<Produit> GetFromSitesAsync(List<string> productSites) { // 构造过滤条件:嵌套数组foobar中存在至少一个元素的uid在入参数组范围内 var filter = Builders<Produit>.Filter.ElemMatch( product => product.foobar, foobar => productSites.Contains(foobar.uid) ); // Find方法默认返回不重复的文档,不需要额外去重 // 如果需要按业务字段(如uid)二次去重,可使用Distinct方法 return _produits.Find(filter).ToList(); }
原有写法异常排查
如果要继续使用BsonDocument写法,可按以下两点排查:
- 确认字段映射关系:如果实体类中嵌套数组的属性名是
Bars,但MongoDB中存储的字段名为foobar,需要给属性添加[BsonElement("foobar")]注解,或直接将BsonDocument中的字段名改为和实体类属性名一致。 - 确认入参格式:检查入参
productSites的元素是否存在前后空格、大小写不匹配的情况,保证和数据库存储的uid格式完全一致。
内容的提问来源于stack exchange,提问作者Taieb
相关产品推荐
相关产品推荐

