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

MongoDB $setDifference

Dans MongoDB, le $setDifference L'opérateur de pipeline d'agrégation accepte deux ensembles et effectue un complément relatif du second ensemble par rapport au premier. Il renvoie un tableau contenant les éléments qui n'existent que dans le premier ensemble.

$setDifference accepte deux arguments, qui peuvent tous deux être n'importe quelle expression valide tant qu'ils se résolvent chacun en un tableau. $setDifference traite les tableaux comme des ensembles.

Exemple

Supposons que nous ayons une collection appelée data avec les documents suivants :

{ "_id" :1, "a" :[ 1, 2, 3 ], "b" :[ 1, 2, 3 ] }{ "_id" :2, "a" :[ 1, 2, 3 ], "b" :[ 1, 2 ] }{ "_id" :3, "a" :[ 1, 2 ], "b" :[ 1, 2, 3 ] }{ "_id" :4, " a" :[ 1, 2, 3 ], "b" :[ 3, 4, 5 ] }{ "_id" :5, "a" :[ 1, 2, 3 ], "b" :[ 4, 5 , 6 ] }

Nous pouvons appliquer le $setDifference opérateur contre le a et b champs dans ces documents.

Exemple :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3, 4, 5 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

{ "a" :[ 1, 2, 3 ], "b" :[ 1, 2, 3 ], "résultat" :[ ] }{ "a" :[ 1, 2, 3 ], "b " :[ 1, 2 ], "résultat" :[ 3 ] }{ "a" :[ 1, 2 ], "b" :[ 1, 2, 3 ], "résultat" :[ ] }{ "a" :[ 1, 2, 3 ], "b" :[ 3, 4, 5 ], "résultat" :[ 1, 2 ] }{ "a" :[ 1, 2, 3 ], "b" :[ 4 , 5, 6 ], "résultat" :[ 1, 2, 3 ] }

Tableaux imbriqués

Le $setDifference L'opérateur ne descend dans aucun tableau imbriqué. Il évalue uniquement les tableaux de niveau supérieur.

Supposons que notre collection contienne également les documents suivants :

{ "_id" :6, "a" :[ 1, 2, 3 ], "b" :[ [ 1, 2, 3 ] ] }{ "_id" :7, "a" :[ 1, 2, 3 ], "b" :[ [ 1, 2 ], 3 ] }

Et nous appliquons $setDifference à ces deux documents :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 6, 7 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

{ "a" :[ 1, 2, 3 ], "b" :[ [ 1, 2, 3 ] ], "résultat" :[ 1, 2, 3 ] }{ "a" :[ 1, 2, 3 ], "b" :[ [ 1, 2 ], 3 ], "résultat" :[ 1, 2 ] }

Dans le premier document, le b champ contenait un tableau qui ne contenait qu'un seul élément - un autre tableau. Dans ce cas, le tableau externe a été évalué et il s'est avéré qu'il ne contenait pas les mêmes valeurs que celles qui se trouvaient dans le tableau à a .

Cependant, si le a champ contenait lui-même un tableau imbriqué, cela aurait pu être une autre histoire.

Supposons que nous ayons les documents suivants :

{ "_id" :8, "a" :[ [ 1, 2, 3 ] ], "b" :[ [ 1, 2, 3 ] ] }{ "_id" :9, "a" :[ [ 1, 2, 3 ] ], "b" :[ [ 1, 2 ], 3 ] }

Et nous appliquons $setDifference à ces documents :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 8, 9 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

{ "a" :[ [ 1, 2, 3 ] ], "b" :[ [ 1, 2, 3 ] ], "résultat" :[ ] }{ "a" :[ [ 1, 2, 3 ] ], "b" :[ [ 1, 2 ], 3 ], "résultat" :[ [ 1, 2, 3 ] ] }

Dans le premier document, a correspond à b exactement, et donc le résultat est un tableau vide.

Dans le deuxième document, le tableau imbriqué à a est différent du tableau imbriqué à b , et donc tout le tableau imbriqué de a est renvoyé.

Champs manquants

Application de $setDifference à un champ inexistant donne null .

Considérez les documents suivants :

{ "_id" :10, "a" :[ 1, 2, 3 ] }{ "_id" :11, "b" :[ 1, 2, 3 ] }{ "_id" :12 } 

Le premier document n'a pas de b champ, le deuxième document n'a pas de a champ, et le troisième document n'a ni l'un ni l'autre.

Voici ce qui se passe lorsque nous appliquons $setDifference au a et b champs :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 10, 11, 12 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

{ "a" :[ 1, 2, 3 ], "result" :null }{ "b" :[ 1, 2, 3 ], "result" :null }{ "result" :null } 

Type de données incorrect

Les deux opérandes de $setDifference doivent être des tableaux. Si ce n'est pas le cas, une erreur est générée.

Supposons que notre collection contienne les documents suivants :

{ "_id" :13, "a" :[ 1, 2, 3 ], "b" :3 }{ "_id" :14, "a" :3, "b" :[ 1, 2, 3 ] }{ "_id" :15, "a" :2, "b" :3 }

Et nous appliquons $setDifference à ces documents :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 13, 14, 15 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

exception non détectée :erreur :échec de la commande :{ "ok" :0, "errmsg" :"les deux opérandes de $setDifference doivent être des tableaux. Le deuxième argument est de type :double", "code" :17049, "codeName" :"Location17049"} :l'agrégat a échoué :[email protected]/mongo/shell/utils.js:25:[email protected]/mongo/shell/assert.js:18:[email protected]/mongo/shell /assert.js:639:[email protected]/mongo/shell/assert.js:729:[email protected]/mongo/shell/db.js:266:[email protected]/mongo/shell/collection .js:1058:12@(shell):1:1

Valeurs en double

Le $setDifference L'opérateur filtre les doublons dans son résultat pour générer un tableau contenant uniquement des entrées uniques. De plus, l'ordre des éléments dans le tableau de sortie n'est pas spécifié.

Supposons que nous ayons les documents suivants :

{ "_id" :16, "a" :[ 1, 1, 2, 2, 3, 3 ], "b" :[ 1, 2, 3 ] }{ "_id" :17, "a" :[ 1, 1, 2, 2, 3, 3 ], "b" :[ 1, 2 ] }{ "_id" :18, "a" :[ 1, 1, 2, 2, 3, 3 ], "b" :[ ] }{ "_id" :19, "a" :[ 3, 2, 1, 2, 3, 1 ], "b" :[ 2, 3, 1 ] }{ "_id" :20 , "a" :[ 1, 3, 2, 2, 3, 1 ], "b" :[ 2, 1 ] }{ "_id" :21, "a" :[ 2, 3, 1, 2, 3 , 1 ], "b" :[ ] }

Ensuite, nous appliquons le $setDifference opérateur pour eux :

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 16, 17, 18, 19, 20, 21 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
) 

Résultat :

{ "a" :[ 1, 1, 2, 2, 3, 3 ], "b" :[ 1, 2, 3 ], "résultat" :[ ] }{ "a" :[ 1, 1 , 2, 2, 3, 3 ], "b" :[ 1, 2 ], "résultat" :[ 3 ] }{ "a" :[ 1, 1, 2, 2, 3, 3 ], "b" :[ ], "résultat" :[ 1, 2, 3 ] }{ "a" :[ 3, 2, 1, 2, 3, 1 ], "b" :[ 2, 3, 1 ], "résultat" :[ ] }{ "a" :[ 1, 3, 2, 2, 3, 1 ], "b" :[ 2, 1 ], "résultat" :[ 3 ] }{ "a" :[ 2, 3 , 1, 2, 3, 1 ], "b" :[ ], "résultat" :[ 2, 3, 1 ] }