You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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'.

错误原因

  1. Lookup字段顺序颠倒:原生聚合中localField是sectors集合的VirtualChainId,foreignField是virtualChains集合的_id,但C#代码中Lookup参数顺序写反,导致关联数据错误,后续Unwind无法找到正确字段。
  2. Project的JSON格式错误:传入Project的字符串未给JSON键添加双引号,违反JSON语法规范,导致解析失败,这是直接触发报错的原因。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:24:56