从多个字符串字段中解析出数字,将它们添加到 MongoDB 聚合管道中的新字段?

问题描述 投票:0回答:1

我正在尝试想出一种方法来解析

string
类型的三个不同字段中的“数字”,将它们转换为真正的数字类型,并将它们添加到一个新字段中。我必须在聚合管道中执行此操作,以便当我的文档进入我要放置的“组”阶段时,我可以创建所有文档的 item1、item2 和 item3 字段的总和。

该集合包含以下对象:

{
    "groupId": 1,
    "item1": "$300.00 - Jason"
    "item2": "$25.50 - Stephanie"
    "item3": ""
}

每个文档中总会包含三个项目,但并非每个项目都会包含某些内容。

在聚合管道中进行操作后,我希望得到这样的文档:

{
    "groupId": 1,
    "itemTotal": 325.5
}

管道的下一阶段将是按 groupId 对文档进行分组,获取该组的 itemTotal(我可以处理这个问题,因为那时它会很简单)。

我尝试的第一件事是 $regexFind 但看起来我一次只能在一个字段上运行它,我希望我可以解析所有三个数字并一步添加它们。据我所知,前进的唯一途径是做类似的事情:

db.collection.aggregate([
    {
        $project: {
            item1NumberString: { $regexFind: {input: "item1", regex: /\$(\d{1,}\.\d\d)/} },
            item2NumberString: { $regexFind: {input: "item2", regex: /\$(\d{1,}\.\d\d)/} },
            item3NumberString: { $regexFind: {input: "item3", regex: /\$(\d{1,}\.\d\d)/} }
        }
    },
    {
        $addFields: {
            "itemTotal": {$add: [
                {$toInt: "$item1NumberString.captures.0"}, 
                {$toInt: "$item2NumberString.captures.0"}, 
                {$toInt: "item3NumberString.captures.0"} 
            ] } 
        }
    }
]);

但如果没有必要,将其分解为多个管道阶段似乎效率低下。有没有更简单的方法来实现这一点?也许通过创造性地使用连接运算符或其他东西?

我还需要将此答案转换为 Spring MongoDB 查询

mongodb aggregation-framework spring-data-mongodb
1个回答
0
投票

对 3 个字段重复以下步骤:

  1. 除以
    -
    并获得第一个令牌/部分
  2. 删除美元符号
  3. $convert
    将字符串更改为双倍

然后对 3 个解析后的双精度数求和。

db.collection.aggregate([
  {
    $set: {
      // split by - and get first token
      item1Parsed: {
        $first: {
          "$split": [
            "$item1",
            " - "
          ]
        }
      },
      item2Parsed: {
        $first: {
          "$split": [
            "$item2",
            " - "
          ]
        }
      },
      item3Parsed: {
        $first: {
          "$split": [
            "$item3",
            " - "
          ]
        }
      }
    }
  },
  {
    "$set": {
      // remove dollar sign
      "item1Parsed": {
        "$replaceAll": {
          "input": "$item1Parsed",
          "find": {
            $literal: "$"
          },
          "replacement": ""
        }
      },
      "item2Parsed": {
        "$replaceAll": {
          "input": "$item2Parsed",
          "find": {
            $literal: "$"
          },
          "replacement": ""
        }
      },
      "item3Parsed": {
        "$replaceAll": {
          "input": "$item3Parsed",
          "find": {
            $literal: "$"
          },
          "replacement": ""
        }
      }
    }
  },
  {
    $set: {
      // parse to double
      item1Parsed: {
        "$convert": {
          "input": "$item1Parsed",
          "to": "double",
          "onError": 0.0
        }
      },
      item2Parsed: {
        "$convert": {
          "input": "$item2Parsed",
          "to": "double",
          "onError": 0.0
        }
      },
      item3Parsed: {
        "$convert": {
          "input": "$item3Parsed",
          "to": "double",
          "onError": 0.0
        }
      }
    }
  },
  {
    $project: {
      // sum them up
      groupId: 1,
      itemTotal: {
        $sum: [
          "$item1Parsed",
          "$item2Parsed",
          "$item3Parsed"
        ]
      }
    }
  }
])

蒙戈游乐场

© www.soinside.com 2019 - 2024. All rights reserved.