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

MongoDB聚合查询:匹配动态键对应的对象字段值

Absolutely, MongoDB does support this kind of dynamic field check in aggregations—your original approach just had a couple of key issues that were preventing it from working. Let's break down what went wrong and fix it.

The main problem with your initial code is that you can't use a variable like $UserId directly in a field path within the $match stage. MongoDB parses field names statically in stages like $match, so it won't interpret data[$UserId].value as a dynamic reference to the field named after info.id. Also, there were some syntax errors (misplaced quotes and brackets) in your pipeline.

To handle dynamic field keys like this, we need to convert the data object into an array (so we can work with its keys/values programmatically) or use aggregation expressions to dynamically fetch the field value. Here are two solid approaches:

Approach 1: Convert the data object to an array

This is a straightforward method that works across most MongoDB versions:

db.yourCollectionName.aggregate([
  // Step 1: Convert data object to an array of {k: key, v: value} pairs, and convert info.id to string (since data keys are strings)
  {
    $addFields: {
      dataArray: { $objectToArray: "$data" },
      targetKey: { $toString: "$info.id" }
    }
  },
  // Step 2: Extract the specific data entry matching our target key
  {
    $addFields: {
      targetEntry: {
        $arrayElemAt: [
          {
            $filter: {
              input: "$dataArray",
              cond: { $eq: ["$$this.k", "$targetKey"] }
            }
          },
          0
        ]
      }
    }
  },
  // Step 3: Match only documents where the target entry's value is greater than 10
  {
    $match: {
      "targetEntry.v.value": { $gt: 10 }
    }
  },
  // Optional: Clean up the output to only include fields you need
  {
    $project: {
      UserId: "$info.id",
      matchedValue: "$targetEntry.v.value",
      _id: 0
    }
  }
])

Approach 2: Use $getField with a dynamic key (MongoDB 5.0+)

If you're using MongoDB 5.0 or later, you can use the $getField operator to directly fetch the dynamic field, making the pipeline much shorter:

db.yourCollectionName.aggregate([
  {
    $match: {
      $expr: {
        $gt: [
          // Dynamically get the value of data.[info.id].value
          {
            $let: {
              vars: {
                // Fetch the object from data using the stringified info.id as the key
                targetObj: {
                  $getField: {
                    field: { $toString: "$info.id" },
                    input: "$data"
                  }
                }
              },
              in: "$$targetObj.value" // Extract the 'value' property from that object
            }
          },
          10 // Compare against 10
        ]
      }
    }
  }
])

Key Notes:

  • String conversion for matching: We use $toString on $info.id because your data object has string keys ("123", "234") while info.id is a number (123)—matching data types is required for the comparison to work.
  • $expr in $match: This operator lets us use aggregation expressions (like dynamic field lookups) within the $match stage, which is essential for this kind of dynamic check.

Either of these pipelines will let you perform the check directly in MongoDB, no need to handle it on the server side.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:47:54