sql >> Database >  >> NoSQL >> MongoDB

MongoDB $setDifference

In MongoDB, de $setDifference aggregatiepijplijnoperator accepteert twee sets en voert een relatieve aanvulling uit van de tweede set ten opzichte van de eerste. Het geeft een array terug met de elementen die alleen in de eerste set voorkomen.

$setDifference accepteert twee argumenten, die beide elke geldige expressie kunnen zijn, zolang ze elk naar een array worden omgezet. $setDifference behandelt de arrays als sets.

Voorbeeld

Stel dat we een verzameling hebben met de naam data met de volgende documenten:

{ "_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 ] }

We kunnen de $setDifference . toepassen operator tegen de a en b velden in die documenten.

Voorbeeld:

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

Resultaat:

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

Geneste arrays

De $setDifference operator daalt niet af in geneste arrays. Het evalueert alleen arrays op het hoogste niveau.

Stel dat onze collectie ook de volgende documenten bevat:

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

En we passen $setDifference toe naar die twee documenten:

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

Resultaat:

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

In het eerste document, de b veld bevatte een array die slechts één element bevatte - een andere array. In dit geval is de buitenste array geëvalueerd en bleek deze niet dezelfde waarden te bevatten als in de array op a .

Als de a veld zelf een geneste array had bevat, was het misschien een ander verhaal geweest.

Stel dat we de volgende documenten hebben:

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

En we passen $setDifference toe naar die documenten:

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

Resultaat:

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

In het eerste document, a komt overeen met b precies, en dus is het resultaat een lege array.

In het tweede document, de geneste array op a is anders dan de geneste array op b , en dus de hele geneste array van a wordt geretourneerd.

Ontbrekende velden

$setDifference toepassen naar een niet-bestaand veld resulteert in null .

Bekijk de volgende documenten:

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

Het eerste document heeft geen b veld, heeft het tweede document geen a veld, en het derde document heeft geen van beide.

Dit is wat er gebeurt als we $setDifference toepassen naar de a en b velden:

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

Resultaat:

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

Onjuist gegevenstype

Beide operanden van $setDifference moeten arrays zijn. Als dat niet het geval is, wordt er een fout gegenereerd.

Stel dat onze collectie de volgende documenten bevat:

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

En we passen $setDifference toe naar die documenten:

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

Resultaat:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "both operands of $setDifference must be arrays. Second argument is of type: double",
	"code" : 17049,
	"codeName" : "Location17049"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Dubbele waarden

De $setDifference operator filtert duplicaten uit het resultaat om een ​​array uit te voeren die alleen unieke items bevat. Ook is de volgorde van de elementen in de uitvoerarray niet gespecificeerd.

Stel dat we de volgende documenten hebben:

{ "_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" : [ ] }

Dan passen we de $setDifference . toe operator voor hen:

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

Resultaat:

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

  1. Converteer DBObject naar een POJO met MongoDB Java Driver

  2. pymongo.errors.CursorNotFound:cursor id '...' niet geldig op server

  3. mongod HostnameCanonicalizationWorker-fout op OS X

  4. Waarom Mongodb-prestaties beter op Linux dan op Windows?