MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mongo / Mongoose Aggregation - Problèmes $redact et $cond

Vous pouvez essayer $facet avec $addFields pour l'agrégation parallèle dans 3.4 version.

Cela réduira la complexité globale et vous pourrez exécuter des regroupements avec sa propre entrée correspondante en même temps.

Le code ci-dessous construit le pipeline d'agrégation de manière dynamique en fonction de l'objet de requête.

// Sample request
var request = {
  "name":"RINGGO",
  "year": 2017,
  "month":3,
  "week":12
};

// Build initial match document on name

var match1 = {
  name: request["name"]
};

// Build project & facet document for date based aggregation

var addFields = {};
var facet = {};

// Add year followed by year facet

if (request["year"]) {
    addFields["year"] = { "$year": "$date" },
    facet["Yearly"] = 
      [
        {
          "$match":{ "year": request["year"] }
        },
        {
          "$group": {
            "_id": {
              "name": "$name",
              "year": "$year"
            },
            "spend": { "$push":"$amount" },
            "total": { "$sum": "$amount" }
        }
      }
    ];
}

// Add month followed by month facet

if (request["month"]) {
    addFields["month"] = { "$month": "$date" };
    facet["Monthly"] = 
      [
        {
          "$match":{ "month": request["month"] }
        },
        {
          "$group": {
            "_id": {
              "name": "$name",
              "month": "$month"
            },
            "spend": { "$push":"$amount" },
            "total": { "$sum": "$amount" }
         }
      }
    ];
}

// Add week followed by week facet

if (request["week"]) {
    addFields["week"] = { "$week": "$date" };
    facet["Weekly"] = 
      [
        {
          "$match":{ "week": request["week"] }
        },
        {
          "$group": {
            "_id": {
              "name": "$name",
              "week": "$week"
            },
            "spend": { "$push":"$amount" },
            "total": { "$sum": "$amount" }
         }
      }
    ];
}

// Use aggregate builder

statements.aggregate()
        .match(match1)
        .append({"$addFields": addFields}) // No addFields stage in mongoose builder
        .facet(facet)
        .exec(function(err, data) {});

Requête Mongo Shell pour name/year/month/week critères.

db.statements.aggregate({
    '$match': {
        name: 'RINGGO'
    }
}, {
    '$addFields': {
        year: {
            '$year': '$date'
        },
        month: {
            '$month': '$date'
        },
        week: {
            '$week': '$date'
        }
    }
}, {
    '$facet': {
        Yearly: [{
                '$match': {
                    year: 2017
                }
            },
            {
                '$group': {
                    _id: {
                        name: '$name',
                        year: '$year'
                    },
                    spend: {
                        '$push': '$amount'
                    },
                    total: {
                        '$sum': '$amount'
                    }
                }
            }
        ],
        Monthly: [{
                '$match': {
                    month: 3
                }
            },
            {
                '$group': {
                    _id: {
                        name: '$name',
                        month: '$month'
                    },
                    spend: {
                        '$push': '$amount'
                    },
                    total: {
                        '$sum': '$amount'
                    }
                }
            }
        ],
        Weekly: [{
                '$match': {
                    week: 12
                }
            },
            {
                '$group': {
                    _id: {
                        name: '$name',
                        week: '$week'
                    },
                    spend: {
                        '$push': '$amount'
                    },
                    total: {
                        '$sum': '$amount'
                    }
                }
            }
        ]
    }
})

Exemple de réponse

    {
    "Yearly": [{
        "_id": {
            "name": "RINGGO",
            "year": 2017
        },
        "spend": [-3.3, -6.3, -3.3, -6.3, -3.3, -3.3],
        "total": -25.799999999999997
    }],
    "Monthly": [{
        "_id": {
            "name": "RINGGO",
            "month": 3
        },
        "spend": [-3.3, -6.3, -3.3, -6.3, -3.3, -3.3],
        "total": -25.799999999999997
    }],
    "Weekly": [{
        "_id": {
            "name": "RINGGO",
            "week": 12
        },
        "spend": [-6.3, -3.3],
        "total": -9.6
    }]
}

Vous pouvez exécuter l'agrégation similaire pour Year/Month et Year valeurs d'entrée.

Cela se produit dans $group 1 où $week l'agrégation cumule chacune des deux dates [15, 16] le montant dans la semaine 11 et les deux autres dates [22, 23] le montant dans la semaine 12 plus tard pour apparaître sous forme de totaux dans MonthySpends .