Jen zde napevno zakóduji některé hodnoty, aby odpovídaly "prvnímu" indexu pole "polaire"
a "druhý" index pole "matrice"
pro demonstraci. Všimněte si zde použití $elemMatch
v $match
fázi agregačního kanálu a použití $map
a $filter
v $project
fáze potrubí:
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")
);
Což znamená tuto serializaci:
[
{ "$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 ] }
]
}
}
}
}
}
}
}}
]
A vytvoří odpovídající výstup dokumentu jako:
{
"_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
]
}
]
}
]
}
Část "dotaz" $match
je důležité skutečně vybrat „dokument(y)“, které splňují podmínky. Bez použití $elemMatch
výraz se může ve skutečnosti shodovat s dokumenty bez správných podmínek na stejných vnitřních prvcích a ve skutečnosti by byl rozložen mezi všechny prvky pole přítomné v dokumentu (dokumentech).
Filtrování pole, které je vnořeno jako první, používá $map
protože „vnitřní“ prvek pole bude také podléhat vlastnímu „filtrování“. Tedy jak "input"
zdroj pro $map
stejně jako "výstup" jako "in"
odkaz na $filter
podmínky, aby odpovídaly konkrétnímu prvku (prvkům) polí.
Jako "podmínky" ( "cond"
) na $filter
používáme "logické agregační výrazy", jako je booleovský $and
stejně jako ostatní „operátory srovnávání“, aby napodobily stejné podmínky jejich protějšků „operátor dotazu“. Ty jsou zodpovědné za logiku, která odpovídá správným položkám pole, které se vrátí ve „filtrovaném“ výsledku.
Pro informaci toto jsou zdrojová data, ze kterých jsou získány výsledky, které by měly být stejné, jako jsou uvedeny v otázce:
{
"_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
]
}
]
}
]
}