In MongoDB, de $setIntersection
aggregatiepijplijnoperator accepteert twee of meer arrays en retourneert een array die de elementen bevat die in alle invoerarrays voorkomen.
$setIntersection
accepteert twee of meer argumenten, die allemaal elke geldige expressie kunnen zijn, zolang ze elk naar een array worden omgezet. $setIntersection
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 $setIntersection
. 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: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
{ "a" : [ 1, 2, 3 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 2, 3 ], "b" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2, 3 ], "b" : [ 3, 4, 5 ], "result" : [ 3 ] } { "a" : [ 1, 2, 3 ], "b" : [ 4, 5, 6 ], "result" : [ ] }
Geneste arrays
De $setIntersection
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 $setIntersection
toe naar die twee documenten:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 6, 7 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
{ "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2, 3 ] ], "result" : [ ] } { "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2 ], 3 ], "result" : [ 3 ] }
In het eerste document, de b
veld bevatte een array die slechts één element bevatte - een andere array. In dit geval werd de buitenste array geëvalueerd en bleek niet een van de waarden bevatten die in de array stonden op a
.
Veronderstel echter 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 ] }
Document 8 bevat een geneste array op zowel de a
en b
velden, en beide arrays zijn identiek.
Dit is wat er gebeurt als we $setIntersection
toepassen naar die documenten:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 8, 9 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
{ "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2, 3 ] ], "result" : [ [ 1, 2, 3 ] ] } { "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2 ], 3 ], "result" : [ ] }
In het eerste document, a
komt overeen met b
precies, en dus is het resultaat een identieke array (een buitenste array die de binnenste array bevat).
In het tweede document, de inhoud van a
komt niet overeen met de inhoud van b
, en dus wordt een lege array geretourneerd.
Ontbrekende velden
$setIntersection
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 $setIntersection
toepassen naar de a
en b
velden:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 10, 11, 12 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
{ "a" : [ 1, 2, 3 ], "result" : null } { "b" : [ 1, 2, 3 ], "result" : null } { "result" : null }
Onjuist gegevenstype
Alle operanden van $setIntersection
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 $setIntersection
toe naar die documenten:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 13, 14, 15 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
Error: command failed: { "ok" : 0, "errmsg" : "All operands of $setIntersection must be arrays. One argument is of type: double", "code" : 17047, "codeName" : "Location17047" } : 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 $setIntersection
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 $setIntersection
. toe operator voor hen:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 16, 17, 18, 19, 20, 21 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultaat:
{ "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ ], "result" : [ ] } { "a" : [ 3, 2, 1, 2, 3, 1 ], "b" : [ 2, 3, 1 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 3, 2, 2, 3, 1 ], "b" : [ 2, 1 ], "result" : [ 1, 2 ] } { "a" : [ 2, 3, 1, 2, 3, 1 ], "b" : [ ], "result" : [ ] }
Meer dan twee argumenten
Zoals vermeld, $setIntersection
accepteert twee of meer argumenten. Alle voorgaande voorbeelden gebruikten twee argumenten. Hier is er een die drie argumenten gebruikt.
Stel dat we de volgende documenten hebben:
{ "_id" : 22, "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2 ] } { "_id" : 23, "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2, 3 ] }
Deze documenten hebben een extra veld – een c
veld.
Laten we nu $setIntersection
. toepassen naar die drie velden:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 22, 23 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
c: 1,
result: { $setIntersection: [ "$a", "$b", "$c" ] }
}
}
]
)
Resultaat:
{ "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2, 3 ], "result" : [ 1, 2 ] }