我一直在开发一个应用程序来跟踪我的交易卡收藏。我正在尝试使用聚合管道在数据库级别对卡片进行排序,因为此应用程序将包含大量数据。我对聚合非常陌生,而且我一直遇到这样的问题:我的 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,但它仍然显示为未定义。
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 },
];