【发布时间】:2017-11-12 07:09:48
【问题描述】:
如何从嵌套数组中提取数据?
我想提取数组项“values”,其中 wind_speed 参数值介于 vitRange.min 和 vitRange.max 之间(twaRange 和风向的条件相同)
数据:
{
"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]
}
]
}
]
}
第一种方法:
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);
第二种方法:
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);
最后一种方法: (参见Query a document and all of its subdocuments that match a condition in mongodb (using 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();
或者另一个...
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();
在论坛上一次又一次地转,但没有一个能帮助我。 问题可能在于处理 json 结构(使其适应轻松请求)?
谢谢
【问题讨论】:
-
见
$elemMatch。这是您想要匹配数组元素中的多个条件的操作。否则,条件将应用于所有个可能的数组位置。您想要一个“奇异”元素来匹配条件。或者至少所有这些条件都适用于满足它们的所有“奇异”元素。 -
您的问题没有显示
$elemMatch条件,因此这可能会导致错误的结果,需要更正。但是你还有另一个问题,你也有嵌套数组。 positional$operator 只能匹配 "first" 和 "outer" 数组位置,这使得投影任何内部数组成为不可能。因此,在修复初始查询后,您需要使用$filter或类似的聚合操作来匹配它。 -
参见Retrieve only the queried element in an object array in MongoDB collection了解更多细节和示例。您需要在此处进行一些研究以了解其工作原理。
-
另外,当您的问题实际上并不存在这样的尝试时,请不要做出诸如 “我尝试这个但没有成功...”之类的声明。如果您“尝试过”,则在代码中包含Edit。然后我们都可以看到你真正尝试了什么,然后告诉你是对还是错。
标签: mongodb spring-boot aggregation-framework spring-data-mongodb