无效的 $addFields :: 由 :: 未定义变量引起:setNumberPart

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

我一直在开发一个应用程序来跟踪我的交易卡收藏。我正在尝试使用聚合管道在数据库级别对卡片进行排序,因为此应用程序将包含大量数据。我对聚合非常陌生,而且我一直遇到这样的问题:我的 setNumberPart 变量在引用时超出范围,并且我似乎无法找到在范围内的方法。这是我的管道代码:

        const pipeline = [
          { $match: query }, // Match documents based on the query

          {
            $addFields: {
              numericSetNumber: {
                $let: {
                  vars: {
                    // Extract the relevant part of setNumber based on prefix
                    setNumberPart: {
                      $cond: [
                        { $regexMatch: { input: "$setNumber", regex: /^GG/ } },
                        { $arrayElemAt: [{ $split: ["$setNumber", "/"] }, 0] },
                        {
                          $cond: [
                            {
                              $regexMatch: {
                                input: "$setNumber",
                                regex: /^TG/,
                              },
                            },
                            {
                              $arrayElemAt: [
                                { $split: ["$setNumber", "/"] },
                                0,
                              ],
                            },
                            {
                              $cond: [
                                {
                                  $regexMatch: {
                                    input: "$setNumber",
                                    regex: /^SWSH/,
                                  },
                                },
                                {
                                  $arrayElemAt: [
                                    { $split: ["$setNumber", " "] },
                                    -1,
                                  ],
                                },
                                "$setNumber", // Default case if no prefix matches
                              ],
                            },
                          ],
                        },
                      ],
                    },
                    // Remove non-numeric characters from setNumberPart
                    cleanedSetNumber: {
                      $replaceAll: {
                        input: "$$setNumberPart",
                        find: "[^0-9]", // Pattern to keep only numeric characters
                        replacement: "",
                      },
                    },
                  },
                  in: {
                    // Convert cleaned number to integer or default to 0 if empty
                    $cond: [
                      {
                        $regexMatch: {
                          input: "$$cleanedSetNumber",
                          regex: /^\d+$/, // Ensure it's numeric
                        },
                      },
                      { $toInt: { $ifNull: ["$$cleanedSetNumber", "0"] } },
                      0,
                    ],
                  },
                },
              },
            },
          },

          ...(Object.keys(sortStage).length > 0 ? [{ $sort: sortStage }] : []),
          { $skip: offset },
          { $limit: limit },
        ];

非常感谢任何帮助使该变量停止未定义的行为!

我尝试在cleanedSetNumber变量中添加另一个$let并在那里定义$$setNumberPart,但它仍然显示为未定义。

javascript mongodb mongoose aggregate pipeline
1个回答
0
投票
The problem you're encountering is due to a scoping issue in MongoDB's aggregation framework. When you use the $let operator, variables defined within vars (such as setNumberPart) are only available inside the in clause of the same $let expression. Since you're trying to reference setNumberPart outside of the in clause, the variable is considered out of scope.

To solve this, you need to perform the $replaceAll operation within the same $let scope where setNumberPart is defined. This way, all operations involving setNumberPart stay within the same $let expression, ensuring they are in scope.

Here's a revised version of your pipeline that keeps all operations within scope:`enter code here`
const pipeline = [
  { $match: query }, // Match documents based on the query

  {
    $addFields: {
      numericSetNumber: {
        $let: {
          vars: {
            // Extract the relevant part of setNumber based on prefix
            setNumberPart: {
              $cond: [
                { $regexMatch: { input: "$setNumber", regex: /^GG/ } },
                { $arrayElemAt: [{ $split: ["$setNumber", "/"] }, 0] },
                {
                  $cond: [
                    { $regexMatch: { input: "$setNumber", regex: /^TG/ } },
                    { $arrayElemAt: [{ $split: ["$setNumber", "/"] }, 0] },
                    {
                      $cond: [
                        { $regexMatch: { input: "$setNumber", regex: /^SWSH/ } },
                        { $arrayElemAt: [{ $split: ["$setNumber", " "] }, -1] },
                        "$setNumber", // Default case if no prefix matches
                      ],
                    },
                  ],
                },
              ],
            },
          },
          in: {
            // Remove non-numeric characters from setNumberPart
            cleanedSetNumber: {
              $replaceAll: {
                input: "$$setNumberPart",
                find: "[^0-9]", // Pattern to keep only numeric characters
                replacement: "",
              },
            },
          },
        },
      },
    },
  },
  {
    $addFields: {
      numericSetNumber: {
        $cond: [
          {
            $regexMatch: {
              input: "$numericSetNumber.cleanedSetNumber",
              regex: /^\d+$/, // Ensure it's numeric
            },
          },
          { $toInt: { $ifNull: ["$numericSetNumber.cleanedSetNumber", "0"] } },
          0,
        ],
      },
    },
  },
  ...(Object.keys(sortStage).length > 0 ? [{ $sort: sortStage }] : []),
  { $skip: offset },
  { $limit: limit },
];
© www.soinside.com 2019 - 2024. All rights reserved.