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

如何捕获MongoDB中对象内指定数组变更的变更流

MongoDB变更流过滤器:仅监听特定文档的inventory.0.APPLE变更

问题场景

需要配置MongoDB变更流,仅检测特定_id文档中inventory.0.APPLE字段(包括其子字段)的变更,同时忽略inventory.0.DiscountBin.APPLE的任何变更。现有过滤器未达到预期效果。

示例文档

{
    "_id": { "$oid": "64d43991678e200790d54c01" },
    "GroceryPlatform": "FruitBasket",
    "StoreName": "Fruit Kingdom",
    "groceryType": "Assorted",
    "storeID": "64d43991678e200790d54c01",
    "inventory": [{
        "Discounts": "Online",
        "Info1": {
            "Layout": "Honeycomb",
            "Lighting": "Grid",
            "Fitout": "Modern Black",
            "Version": "12.2.0"
        },
        "Info3": {
            "Eftpos": { "$numberInt": "51" },
            "Version": "45.1.11"
        },
        "EnergySaver": "ON",
        "NetworkInfo2": {
            "Hostname": "FruitBasket-010100",
            "IPAddress": "10.10.20.227"
        },
        "APPLE": {
            "Quality": { "$numberDouble": "70.868" },
            "Weight": { "$numberDouble": "0.291" },
            "Color": { "$numberDouble": "0.78" },
            "UsedBy": { "$numberDouble": "4.59" }
        },
        "Time": "2023-08-20T08:50:27",
        "TotalStock": { "$numberInt": "24" },
        "AverageCost": { "$numberInt": "19" },
        "WASTE": { "PowerDelta": { "$numberInt": "45" } },
        "DiscountBin": {
            "APPLE": {
                "Quality": { "$numberDouble": "70.868" },
                "Weight": { "$numberDouble": "0.291" },
                "Color": { "$numberDouble": "0.78" },
                "UsedBy": { "$numberDouble": "4.59" }
            },
            "Time": "2023-08-20T08:43:39"
        }
    }],
    "__v": { "$numberInt": "0" }
}

现有过滤器问题

原过滤器直接判断updateDescription.updatedFields.inventory.0.APPLE是否存在,仅能捕获整个APPLE对象被替换的情况,无法匹配其子字段(如inventory.0.APPLE.Quality)的变更;同时无法区分目标APPLE和DiscountBin下的APPLE字段。

{
  $match: {
    $and: [
      { 'fullDocument._id': new mongoose.Types.ObjectId(documentId) },
      { 'updateDescription.updatedFields': { $exists: true } },
      { 'updateDescription.updatedFields.inventory.0.APPLE': { $exists: true } }
    ]
  }
}

解决方案

通过$expr结合$objectToArray将updatedFields转为键值数组,再用$filter筛选符合路径规则的字段:

  • 匹配以inventory.0.APPLE开头的路径(包括整个对象和子字段)
  • 排除以inventory.0.DiscountBin.APPLE开头的路径

完整过滤器代码:

{
  $match: {
    'fullDocument._id': new mongoose.Types.ObjectId(documentId),
    'updateDescription.updatedFields': { $exists: true },
    $expr: {
      $gt: [
        {
          $size: {
            $filter: {
              input: { $objectToArray: '$updateDescription.updatedFields' },
              cond: {
                $and: [
                  // 匹配目标APPLE路径(含子字段)
                  { $regexMatch: { input: '$$this.k', regex: '^inventory\\.0\\.APPLE(\\.|$)' } },
                  // 排除DiscountBin下的APPLE路径
                  { $not: { $regexMatch: { input: '$$this.k', regex: '^inventory\\.0\\.DiscountBin\\.APPLE' } } }
                ]
              }
            }
          }
        },
        0
      ]
    }
  }
}

逻辑说明

  1. $objectToArray: '$updateDescription.updatedFields':将更新字段的键值对转为[{k: 路径, v: 值}, ...]格式的数组
  2. $regexMatch:用正则匹配路径:
    • ^inventory\.0\.APPLE(\.|$):匹配inventory.0.APPLE本身,或其下的子字段(如inventory.0.APPLE.Quality)
    • $not: { $regexMatch: ... }:排除所有inventory.0.DiscountBin.APPLE开头的路径
  3. $size判断筛选后的数组长度大于0,说明存在符合条件的更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:47:16