Spring数据匹配和过滤嵌套数组

如何从嵌套数组中提取数据?

我想提取其中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);

最后一种方法:(请参见查询文档及其与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();

或另一个…

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结构(使其易于请求)方面?

谢谢

回答:

我将在此处硬编码一些值以匹配的“第一个”数组索引"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")

);

转化为以下序列化:

[

{ "$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 ] }

]

}

}

}

}

}

}

}}

]

并产生匹配的文档输出为:

{

"_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

]

}

]

}

]

}

的“查询”部分$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

]

}

]

}

]

}

以上是 Spring数据匹配和过滤嵌套数组 的全部内容, 来源链接: utcz.com/qa/410224.html

回到顶部