Ho solo intenzione di codificare alcuni valori qui in modo che corrispondano al "primo" indice di matrice di "polaire"
e il "secondo" indice di matrice di "matrice"
per dimostrazione. Nota qui l'uso di $elemMatch
nel $match
fase della pipeline di aggregazione e utilizzo di $map
e $filter
nel $project
fase della pipeline:
Aggregation aggregation = newAggregation(
match(
Criteria.where("name").is("race").and("polaire").elemMatch(
Criteria.where("voile").is("foc")
.and("matrice").elemMatch(
Criteria.where("vitRange.min").lt(5)
.and("vitRange.max").gt(5)
.and("twaRange.min").lt(32)
.and("twaRange.max").gt(32)
)
)
),
project("name")
.and(new AggregationExpression() {
@Override
public DBObject toDbObject(AggregationOperationContext context) {
return new BasicDBObject("$map",
new BasicDBObject("input",new BasicDBObject(
"$filter", new BasicDBObject(
"input", "$polaire")
.append("as","p")
.append("cond", new BasicDBObject("$eq", Arrays.asList("$$p.voile","foc")))
))
.append("as","p")
.append("in", new BasicDBObject(
"voile", "$$p.voile")
.append("matrice",new BasicDBObject(
"$filter", new BasicDBObject(
"input", "$$p.matrice")
.append("as","m")
.append("cond", new BasicDBObject(
"$and", Arrays.asList(
new BasicDBObject("$lt", Arrays.asList("$$m.vitRange.min", 5)),
new BasicDBObject("$gt", Arrays.asList("$$m.vitRange.max", 5)),
new BasicDBObject("$lt", Arrays.asList("$$m.twaRange.min", 32)),
new BasicDBObject("$gt", Arrays.asList("$$m.twaRange.max", 32))
)
))
))
)
);
}
}).as("polaire")
);
Che si traduce in questa serializzazione:
[
{ "$match": {
"name": "race",
"polaire": {
"$elemMatch": {
"voile": "foc",
"matrice": {
"$elemMatch": {
"vitRange.min": { "$lt": 5 },
"vitRange.max": { "$gt": 5 },
"twaRange.min": { "$lt": 32 },
"twaRange.max": { "$gt": 32 }
}
}
}
}
}},
{ "$project": {
"name": 1,
"polaire": {
"$map": {
"input": {
"$filter": {
"input": "$polaire",
"as": "p",
"cond": { "$eq": [ "$$p.voile", "foc" ] }
}
},
"as": "p",
"in": {
"voile": "$$p.voile",
"matrice": {
"$filter": {
"input": "$$p.matrice",
"as": "m",
"cond": {
"$and": [
{ "$lt": [ "$$m.vitRange.min", 5 ] },
{ "$gt": [ "$$m.vitRange.max", 5 ] },
{ "$lt": [ "$$m.twaRange.min", 32 ] },
{ "$gt": [ "$$m.twaRange.max", 32 ] }
]
}
}
}
}
}
}
}}
]
E produce l'output del documento corrispondente come:
{
"_id" : ObjectId("593bc2f15924d4206cc6e399"),
"name" : "race",
"polaire" : [
{
"voile" : "foc",
"matrice" : [
{
"vitRange" : {
"min" : 4,
"max" : 6
},
"twaRange" : {
"min" : 30,
"max" : 33
},
"values" : [
0,
0,
2.4,
3.7
]
}
]
}
]
}
La parte "query" di $match
è importante selezionare effettivamente i "documenti" che soddisfano le condizioni. Senza l'utilizzo di $elemMatch
l'espressione può effettivamente corrispondere a documenti senza le condizioni corrette sugli stessi elementi interni e infatti sarebbe distribuita su tutti gli elementi dell'array presenti nei documenti.
Il filtraggio dell'array nidificato per primo utilizza $map
poiché anche l'elemento dell'array "interno" sarà soggetto al proprio "filtro". Quindi entrambi "input"
fonte per la $map
così come l'"output" come "in"
fare riferimento a $filter
condizioni per abbinare gli elementi specifici degli array.
Come le "condizioni" ( "cond"
) su $filter
utilizziamo "espressioni di aggregazione logica" come il booleano $and
così come gli altri "operatori di confronto" per imitare le stesse condizioni delle loro controparti "operatore di query". Questi sono responsabili della logica che corrisponde agli elementi dell'array corretti da restituire nel risultato "filtrato".
Per riferimento questa è la fonte dei dati da cui si ottengono i risultati che dovrebbero essere gli stessi pubblicati nella domanda:
{
"_id" : ObjectId("593bc2f15924d4206cc6e399"),
"name" : "race",
"polaire" : [
{
"voile" : "foc",
"matrice" : [
{
"vitRange" : {
"min" : 0,
"max" : 4
},
"twaRange" : {
"min" : 0,
"max" : 30
},
"values" : [
0,
0,
0,
2.4
]
},
{
"vitRange" : {
"min" : 4,
"max" : 6
},
"twaRange" : {
"min" : 30,
"max" : 33
},
"values" : [
0,
0,
2.4,
3.7
]
}
]
},
{
"voile" : "spi",
"matrice" : [
{
"vitRange" : {
"min" : 0,
"max" : 4
},
"twaRange" : {
"min" : 0,
"max" : 30
},
"values" : [
0,
0,
0,
1.4
]
},
{
"vitRange" : {
"min" : 4,
"max" : 6
},
"twaRange" : {
"min" : 30,
"max" : 33
},
"values" : [
0,
0,
1.4,
2.2
]
}
]
}
]
}