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

Problèmes de structure d'agrégation SailsJS et MongoDB avec des requêtes personnalisées

Votre première requête était sur la bonne voie puisque vous utilisiez le mauvais opérateur de pipeline.

Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "total": { "$size": "$dubs" }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

Bien sûr, le $size l'opérateur nécessite que vous ayez besoin d'une version MongoDB 2.6 ou supérieure, ce que vous devriez probablement faire maintenant, mais vous pouvez toujours faire la même chose sans l'opérateur pour mesurer la longueur du tableau :

Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "dubs": {
                    "$cond": [
                       { "$eq": [ "$dubs", [] ] },
                       [0],
                       "$dubs"
                    ]
                }
            }},
            { "$unwind": "$dubs" },
            { "$group": {
                "_id": "$_id",
                "name": { "$first": "$name" },
                "total": { 
                    "$sum": {
                        "$cond": [
                            { "$eq": [ "$dubs", 0 ] },
                            0,
                            1
                        ]
                    }
                }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

Cela fait la même chose en comptant les membres du tableau, mais à la place, vous auriez besoin de $unwind les éléments du tableau afin de les compter. Donc, cela peut toujours être fait mais n'est pas aussi efficace.

De plus, vous devez gérer les cas où le tableau est vraiment vide mais présent en raison de la façon dont $unwind traite un tableau vide [] . S'il n'y avait pas de contenu, le document qui contenait un tel élément serait supprimé des résultats. De la même manière, vous devrez utiliser $ifNull pour définir un tableau où le document ne contient même pas d'élément pour $unwind pour ne pas générer d'erreur.

Vraiment, si vous avez l'intention de faire ce genre de requête de manière régulière, vous devez conserver un champ "total" dans le document plutôt que de chercher à le calculer en premier. Utilisez le $inc opérateur avec des opérations telles que $push et $pull pour conserver un décompte de la longueur actuelle du tableau.

Cela s'éloigne un peu de la philosophie générale de Waterline, mais vous avez déjà introduit des opérations d'agrégation natives et il n'est pas beaucoup plus difficile de réaliser que vous obtenez de meilleures performances en utilisant des opérations natives dans d'autres domaines également.

Donc, avec des documents comme ceux-ci :

{
  "dubs": [{},{},{}],
  "name": "The Doors",
  "createdAt": "2014-12-15T15:24:26.216Z",
  "updatedAt": "2014-12-15T15:24:26.216Z",
  "id": "548efd2a436c850000353f4f"
},
{
  "dubs": [],
  "name": "The Beatles",
  "createdAt": "2014-12-15T20:30:33.922Z",
  "updatedAt": "2014-12-15T20:30:33.922Z",
  "id": "548f44e90630d50000e2d61d"
}

Vous obtenez exactement les résultats souhaités dans chaque cas :

{
    "_id" : ObjectId("5494b79d7e22da84d53c8760"),
    "name" : "The Doors",
    "total" : 3
},
{
    "_id" : ObjectId("5494b79d7e22da84d53c8761"),
    "name" : "The Beatles",
    "total" : 0
}