MongoDB聚合查询正常,C#实现Unwind操作报错求助
解决C# MongoDB聚合查询的JSON解析报错问题
问题背景
以下MongoDB原生聚合查询可正常运行并返回结果:
db.sectors.aggregate([ { "$lookup": { "from": "virtualChains", "localField": "VirtualChainId", "foreignField": "_id", "as": "VirtualChains" } }, { "$unwind": "$VirtualChains" }, { "$unwind": "$VirtualChains.ZoneConfigInfos" }, { "$match": { "VirtualChains.ZoneConfigInfos.ZoneId": ObjectId("ZoneId") } }, { "$project": { "_id": 1, "Name": 1, "ArabicName": 1, "Code": 1, "ImageUrl": 1, "ArabicImageUrl": 1, "Index": 1, "Description": 1, "DescriptionAR": 1, "IsVirtual": 1, "StoreId": "$VirtualChains.ZoneConfigInfos.StoreId" } } ])
但在C#中实现该逻辑时出现报错,原C#代码如下:
var virProjectDoc = Utils.GetProjectQuery(Properties.Resources.VIRTUAL_SECTOR_PROJECT); var virSecBuilder = Builders<BsonDocument>.Filter; var virFilter = virSecBuilder.AnyEq("VirtualChains.ZoneConfigInfos.ZoneId", ObjectId.Parse(zoneId)); virFilter &= virSecBuilder.Eq("IsActive", true); var virtuSector = MongoContext.Sectors.Aggregate() .Lookup("virtualChains", "_id", "VirtualChainId", "VirtualChains") .Unwind("VirtualChains") .Unwind("VirtualChains.ZoneConfigInfos") .Match(virFilter) .Project<SectorSummaryExIndex>("{Name:1,ArabicName:1,Code:1,ImageUrl:1,ArabicImageUrl:1,Index:1,Description:1,DescriptionAR:1,IsVirtual:1,StoreId:$VirtualChains.ZoneConfigInfos.StoreId}") .ToList() .OrderBy(c => c.Index); return virtuSector;
报错信息:
JSON reader was expecting a value but found 'VirtualChains'.
若将Unwind改为.Unwind("$VirtualChains"),报错变为:
JSON reader was expecting a value but found '$VirtualChains'.
错误原因
- Lookup字段顺序颠倒:原生聚合中
localField是sectors集合的VirtualChainId,foreignField是virtualChains集合的_id,但C#代码中Lookup参数顺序写反,导致关联数据错误,后续Unwind无法找到正确字段。 - Project的JSON格式错误:传入Project的字符串未给JSON键添加双引号,违反JSON语法规范,导致解析失败,这是直接触发报错的原因。
- Filter条件不合理:Unwind之后
VirtualChains.ZoneConfigInfos已从数组变为单个对象,无需使用AnyEq,直接用Eq即可。
修正后的C#代码
var virSecBuilder = Builders<BsonDocument>.Filter; // 修正Filter:Unwind后使用Eq而非AnyEq var virFilter = virSecBuilder.Eq("VirtualChains.ZoneConfigInfos.ZoneId", ObjectId.Parse(zoneId)); virFilter &= virSecBuilder.Eq("IsActive", true); var virtuSector = MongoContext.Sectors.Aggregate() // 修正Lookup字段顺序:localField是VirtualChainId,foreignField是_id .Lookup("virtualChains", "VirtualChainId", "_id", "VirtualChains") // Unwind直接使用字段名,无需加$前缀 .Unwind("VirtualChains") .Unwind("VirtualChains.ZoneConfigInfos") .Match(virFilter) // 修正Project的JSON格式:给所有键添加双引号,$引用也用双引号包裹 .Project<SectorSummaryExIndex>(@"{ ""Name"": 1, ""ArabicName"": 1, ""Code"": 1, ""ImageUrl"": 1, ""ArabicImageUrl"": 1, ""Index"": 1, ""Description"": 1, ""DescriptionAR"": 1, ""IsVirtual"": 1, ""StoreId"": ""$VirtualChains.ZoneConfigInfos.StoreId"" }") .ToList() .OrderBy(c => c.Index); return virtuSector;
关键修正点说明
- Lookup参数:确保顺序为
(关联集合名, 本地集合关联字段, 外部集合关联字段, 输出字段名),与原生聚合的from、localField、foreignField、as一一对应。 - Project字符串:严格遵循JSON语法,所有键必须用双引号包裹,引用字段的
$符号也要包含在字符串内(用双引号包裹)。 - Unwind调用:C#驱动中Unwind的字符串参数直接写字段名即可,无需添加
$前缀,前提是Lookup已正确生成对应字段。 - Filter条件:Unwind操作会将数组拆分为单个文档,此时匹配嵌套字段直接用
Eq即可,无需AnyEq(AnyEq用于匹配数组中存在符合条件的元素)。
内容的提问来源于stack exchange,提问作者Husney Haneefa
相关产品推荐
相关产品推荐

