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

MongoDB中如何筛选文档并仅返回数组中指定值的元素

问题:MongoDB文档数组中筛选指定值并仅返回符合条件的数组元素

需要在MongoDB的文档数组中查找指定值,仅返回包含该值的数组元素及外层文档数据。

示例文档

集合中的文档结构如下:

{
    "_id": {
      "$oid": "63452345f14f98447b792327e9c"
    },
    "TID": "695742332",
    "DID": "WW*DHD",
    "IndexedSpansUsageCost": [
      {
        "month": {
          "$numberInt": "9"
        },
        "year": "2022",
        "IndexedSpansCost": {
          "$numberDouble": "1.11"
        },
        "IndexedSpansCount": {
          "$numberDouble": "418334.0"
        }
      },
      {
        "month": {
          "$numberInt": "10"
        },
        "year": "2022",
        "IndexedSpansCost": {
          "$numberDouble": "1.11"
        },
        "IndexedSpansCount": {
          "$numberDouble": "432516.0"
        }
      }
    ]
  }

当前尝试的代码及问题

用以下Go代码查询时,能找到包含month=9的文档,但返回的是整个文档(包括month=10的数组元素),无法仅保留匹配的数组项:

multifilter := bson.A{{"IndexedSpansUsageCost.month", bson.D{{"$eq", 9}}}}
cursor, err := collection.Find(context.TODO(), multifilter)
if err != nil {
    panic(err)
}

var resultsTest3 []bson.M
if err = cursor.All(context.TODO(), &resultsTest3); err != nil {
    panic(err)
}

for _, resultTest3 := range resultsTest3 {
    output, err := json.MarshalIndent(resultTest3, "", "    ")
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s\n", output)
}

期望结果

希望返回的文档仅包含符合条件的数组元素:

{
    "_id": {
      "$oid": "63452345f14f98447b792327e9c"
    },
    "TID": "695742332",
    "DID": "WW*DHD",
    "IndexedSpansUsageCost": [
      {
        "month": {
          "$numberInt": "9"
        },
        "year": "2022",
        "IndexedSpansCost": {
          "$numberDouble": "1.11"
        },
        "IndexedSpansCount": {
          "$numberDouble": "418334.0"
        }
      }
    ]
  }

解决方案

方法1:使用聚合管道

通过$match筛选出包含目标元素的文档,再用$project结合$filter过滤数组,只保留符合条件的元素:

MongoDB Shell命令示例

db.collection.aggregate([
  // 第一步:筛选出包含month=9的文档
  { $match: { "IndexedSpansUsageCost.month": 9 } },
  // 第二步:过滤数组,仅保留month=9的元素
  {
    $project: {
      TID: 1,
      DID: 1,
      IndexedSpansUsageCost: {
        $filter: {
          input: "$IndexedSpansUsageCost",
          as: "item",
          cond: { $eq: ["$$item.month", 9] }
        }
      }
    }
  }
])

对应的Go代码实现

pipeline := bson.A{
    // $match阶段:匹配包含目标month的文档
    bson.D{{"$match", bson.D{{"IndexedSpansUsageCost.month", 9}}}},
    // $project阶段:过滤数组
    bson.D{
        {"$project", bson.D{
            {"TID", 1},
            {"DID", 1},
            {"IndexedSpansUsageCost", bson.D{
                {"$filter", bson.D{
                    {"input", "$IndexedSpansUsageCost"},
                    {"as", "item"},
                    {"cond", bson.D{{"$eq", bson.A{"$$item.month", 9}}}},
                }},
            }},
        }},
    },
}

cursor, err := collection.Aggregate(context.TODO(), pipeline)
if err != nil {
    panic(err)
}

var results []bson.M
if err = cursor.All(context.TODO(), &results); err != nil {
    panic(err)
}

for _, result := range results {
    output, err := json.MarshalIndent(result, "", "    ")
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s\n", output)
}

方法2:Find查询时使用投影(MongoDB 3.2+支持)

直接在Find的选项中设置投影,用$filter处理数组,无需聚合:

filter := bson.D{{"IndexedSpansUsageCost.month", 9}}
projection := bson.D{
    {"TID", 1},
    {"DID", 1},
    {"IndexedSpansUsageCost", bson.D{
        {"$filter", bson.D{
            {"input", "$IndexedSpansUsageCost"},
            {"as", "item"},
            {"cond", bson.D{{"$eq", bson.A{"$$item.month", 9}}}},
        }},
    }},
}

cursor, err := collection.Find(context.TODO(), filter, options.Find().SetProjection(projection))
if err != nil {
    panic(err)
}

var results []bson.M
if err = cursor.All(context.TODO(), &results); err != nil {
    panic(err)
}

for _, result := range results {
    output, err := json.MarshalIndent(result, "", "    ")
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s\n", output)
}

关键说明

  • $match:先筛选出包含目标元素的文档,减少后续处理的数据量
  • $filter:遍历数组,仅保留满足cond条件的元素,这里判断数组项的month是否等于9

内容的提问来源于stack exchange,提问作者Spring_Reboot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:05:21