ant*_*y44 6 mongodb aggregation-framework spring-data-mongodb spring-boot
如何从嵌套数组中提取数据?
我想提取数组项"值",其中wind_speed参数值介于vitRange.min和vitRange.max之间(twaRange和wind direction的条件相同)
数据:
{
"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]
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
第一种方法:
Query query = new Query(
Criteria.where("name").is(name)
.andOperator(
Criteria.where("polaire.voile").is(sail),
Criteria.where("polaire.matrice.twaRange.max").lt(wind_direction),
Criteria.where("polaire.matrice.twaRange.min").gte(wind_direction),
Criteria.where("polaire.matrice.vitRange.max").lt(wind_speed),
Criteria.where("polaire.matrice.vitRange.min").gte(wind_speed)
)
);
query.fields().include("polaire.matrice.values");
Polaires data = mongoTemplate.findOne(query, Polaires.class);
Run Code Online (Sandbox Code Playgroud)
第二种方法:
Criteria findPolaireCriteria = Criteria.where("name").is(name);
Criteria findValueCriteria = Criteria.where("polaire").elemMatch(Criteria.where("voile").is(sail))
.andOperator(
Criteria.where("polaire.matrice.twaRange").elemMatch(Criteria.where("max").lt(wind_direction)),
Criteria.where("polaire.matrice.twaRange").elemMatch(Criteria.where("min").gte(wind_direction)),
Criteria.where("polaire.matrice.vitRange").elemMatch(Criteria.where("max").lt(wind_speed)),
Criteria.where("polaire.matrice.vitRange").elemMatch(Criteria.where("min").gte(wind_speed)));
BasicQuery query = new BasicQuery(findPolaireCriteria.getCriteriaObject(), findValueCriteria.getCriteriaObject());
query.fields().include("polaire.matrice.values");
Polaires data = mongoTemplate.findOne(query, Polaires.class);
Run Code Online (Sandbox Code Playgroud)
最后一种方法:(参见查询文档及其与mongodb中的条件匹配的所有子文档(使用spring))
Aggregation aggregation = newAggregation(
match(Criteria.where("name").is(name)
.and("polaire").elemMatch(Criteria.where("voile").is(sail))),
project( "_id", "matrice")
.and(new AggregationExpression() {
@Override
public DBObject toDbObject(AggregationOperationContext aggregationOperationContext ) {
DBObject filter = new BasicDBObject("input", "$matrice")
.append("as", "result")
.append("cond",
new BasicDBObject("$and", Arrays.<Object> asList(
new BasicDBObject("$gte", Arrays.<Object> asList("$$result.vitRange.min", 0)),
new BasicDBObject("$lt", Arrays.<Object> asList("$$result.vitRange.max", 4))
)
)
);
return new BasicDBObject("$filter", filter);
}
}).as("matrice")
);
List<BasicDBObject> dbObjects = mongoTemplate.aggregate(aggregation, "collectionname", BasicDBObject.class).getMappedResults();
Run Code Online (Sandbox Code Playgroud)
或者另一个......
List<AggregationOperation> list = new ArrayList<AggregationOperation>();
list.add(Aggregation.match(Criteria.where("name").is(name)));
list.add(Aggregation.unwind("polaire"));
list.add(Aggregation.match(Criteria.where("polaire.voile").is(sail)));
list.add(Aggregation.unwind("polaire.matrice"));
list.add(Aggregation.match(Criteria.where("polaire.matrice.twaRange").elemMatch(Criteria.where("max").lt(wind_direction))));
list.add(Aggregation.match(Criteria.where("polaire.matrice.twaRange").elemMatch(Criteria.where("min").gte(wind_direction))));
list.add(Aggregation.match(Criteria.where("polaire.matrice.vitRange").elemMatch(Criteria.where("max").lt(wind_speed))));
list.add(Aggregation.match(Criteria.where("polaire.matrice.vitRange").elemMatch(Criteria.where("min").gte(wind_speed))));
list.add(Aggregation.group("id", "polaire.matrice").push("polaire.matrice.values").as("values"));
list.add(Aggregation.project("polaire.matrice","values"));
TypedAggregation<Polaires> agg = Aggregation.newAggregation(Polaires.class, list);
List<BasicDBObject> dbObjects = mongoTemplate.aggregate(agg, "collectionname", BasicDBObject.class).getMappedResults();
Run Code Online (Sandbox Code Playgroud)
在论坛上一次又一次地转身,但他们都没有帮助我.问题可能在于对json结构的工作(使其适应容易请求)?
谢谢
我只是在这里硬编码一些值,以匹配演示的"第一"数组索引"polaire"和"第二"数组索引"matrice".注意这里使用$elemMatch的$match聚集流水线阶段和使用情况$map,并$filter在$project流水线阶段:
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")
);
Run Code Online (Sandbox Code Playgroud)
这转换为此序列化:
[
{ "$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 ] }
]
}
}
}
}
}
}
}}
]
Run Code Online (Sandbox Code Playgroud)
并生成匹配的文档输出为:
{
"_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
]
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
"查询"部分$match对于实际选择满足条件的"文档"很重要.如果没有$elemMatch表达式的使用,实际上可以匹配文档而没有相同内部元素上的正确条件,并且实际上将分布在文档中存在的所有数组元素中.
过滤首先嵌套的数组使用,$map因为"内部"数组元素也将受到其自己的"过滤".因此,"输出"和"输出" 的"input"源都是条件引用,以便匹配数组的特定元素.$map"in"$filter
作为"条件"("cond"),$filter我们利用"逻辑聚合表达式",如布尔值$and以及其他"比较运算符"来模仿其"查询运算符"对应物的相同条件.它们负责匹配正确数组项以在"已过滤"结果中返回的逻辑.
作为参考,这是从中获得结果的源数据,其应与问题中公布的相同:
{
"_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
]
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6912 次 |
| 最近记录: |