如何在Spring-Data-MongoDB [春季data-mongodb]中使用$累加器[mongodb]
我是Spring-Data-MongoDB的新手,我正在开发一种在Spring-Data-MongoDB中执行MongoDB $累加器操作员的方法,但是我不知道为什么我在$ aggipulator上的结果
字段返回null。
现在,我正在MongoDB中填充该集合:
db.game.insertMany([
{ "_id" : 1, "name" : "John", "score" : 10},
{ "_id" : 2, "name" : "Elizabeth", "score" : 10},
{ "_id" : 3, "name" : "James ", "score" : 9},
{ "_id" : 4, "name" : "John", "score" : 5},
{ "_id" : 5, "name" : "Elizabeth", "score" : 10},
{ "_id" : 6, "name" : "John", "score" : 10},
{ "_id" : 7, "name" : "Elizabeth", "score" : 10},
{ "_id" : 8, "name" : "James ", "score" : 8 },
{ "_id" : 9, "name" : "James ", "score" : 8}])
这是MongoDB服务器中的累加器聚合:
db.game.aggregate ([
{
$group :
{
_id : "$name",
avgScore:
{
$accumulator:
{
init: function() {
return { count: 0, sum: 0 }
},
accumulate: function(state, score) {
return {
count: state.count + 1,
sum: state.sum + score
}
},
accumulateArgs: ["$score"],
merge: function(state1, state2) {
return {
count: state1.count + state2.count,
sum: state1.sum + state2.sum
}
},
finalize: function(state) {
return (state.sum / state.count)
},
lang: "js"
}
}
}
}
])
这是我试图通过Spring-Data-MongoDB执行的MongoDB的结果:
{ "_id" : "Elizabeth", "avgScore" : 10 }
{ "_id" : "John", "avgScore" : 8.333333333333334 }
{ "_id" : "James ", "avgScore" : 8.333333333333334 }
这是我的RestController的结果:
[
{
"name": "Elizabeth",
"avgScore": null
},
{
"name": "James ",
"avgScore": null
},
{
"name": "John",
"avgScore": null
}
]
这是模型类
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="game")
public class Game {
@Id
private Integer _id;
private String name;
private Integer score;
public Game() {
super();
// TODO Auto-generated constructor stub
}
public int get_id() {
return _id;
}
public void set_id(Integer _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
}
这是在累加器方法上执行$累加器
运算符的服务,但它返回null:
import java.util.LinkedList;
import java.util.List;
import com.project.ecommercemongo.aggregation.ResultAccumulator;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorAccumulateArgsBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorFinalizeBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorInitArgsBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorInitBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorMergeBuilder;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import org.springframework.stereotype.Service;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import com.project.ecommercemongo.model.Game;
import com.project.ecommercemongo.repository.GameRepository;
@Service
public class GameService {
@Autowired
GameRepository game;
@Autowired
MongoTemplate mongoTemplate;
@Autowired
private MongoOperations mongoOperations;
public List<Game> findAll() {
List<Game> list = game.findAll();
return list;
}
public List<ResultAccumulator> accumulator() {
AccumulatorInitBuilder aib = ScriptOperators.accumulatorBuilder();
AccumulatorInitArgsBuilder aiab = aib.init("function() {return { count: 0, sum: 0 }}");
aib.lang("js");
AccumulatorAccumulateArgsBuilder aaac = aiab
.accumulate("function(state, score) { return {count: state.count + 1,sum: state.sum + score}}");
List<Object> bl = new LinkedList<Object>();
bl.add("score");
AccumulatorMergeBuilder amb = aaac.accumulateArgs(bl);
AccumulatorFinalizeBuilder afb = amb.merge(
"function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}");
// Accumulator a=afbb.build();
Accumulator a = afb.finalize("function(state) {return (state.sum / state.count)}");
Document document = a.toDocument();
/*AggregationExpression expression = new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
Document document1 = document;
return document1;
}
};
Document document2 = expression.toDocument();*/
GroupOperation groupByNameAndAccumulator = group("name").last(String.valueOf(document)).as("avgScore");
Aggregation aggregation = newAggregation(groupByNameAndAccumulator);
List<ResultAccumulator> results = mongoOperations
.aggregate(aggregation, mongoTemplate.getCollectionName(Game.class), ResultAccumulator.class)
.getMappedResults();
// AggregationResults<ResultAccumulator> result =
// mongoTemplate.aggregate(aggregation, "game", ResultAccumulator.class);
System.out.println(document);
System.out.println(results.toString());
return results;
}
}
这是打印包含累加器文档的服务器操作员,
2022-07-04 00:42:28.696 INFO 13784 --- [nio-8080-exec-2] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:1531}] to localhost:27118
Document{{$accumulator=Document{{init=function() {return { count: 0, sum: 0 }}, accumulate=function(state, score) { return {count: state.count + 1,sum: state.sum + score}}, accumulateArgs=[score], merge=function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}, lang=js, finalize=function(state) {return (state.sum / state.count)}}}}}
[com.project.mongo.aggregation.ResultAccumulator@37517d96, com.project.mongo.aggregation.ResultAccumulator@19e6b063, com.project.emongo.aggregation.ResultAccumulator@3d69a1a5]
这是结果类,
import org.springframework.data.annotation.Id;
public class ResultAccumulator {
@Id
private String name;
private Double avgScore;
public ResultAccumulator() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getAvgScore() {
return avgScore;
}
public void setAvgScore(Double avgScore) {
this.avgScore = avgScore;
}
}
这是我不知道我在做什么的控制器
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.project.ecommercemongo.aggregation.ResultAccumulator;
import com.project.ecommercemongo.model.Game;
import com.project.ecommercemongo.service.GameService;
@RestController
@RequestMapping("/game")
public class GameController {
@Autowired
GameService service;
@GetMapping("/find")
public List<Game> listAll() {
return service.findAll();
}
@GetMapping("/accumulator")
public List<ResultAccumulator> accumulator() {
return service.accumulator();
}
}
,也许问题在对象累加器
中。 再见,预先感谢您!
更新 现在它奏效了,我的错误是在小组中的最后一个方法上,现在我已经更改为累积(累加器)
AccumulatorInitBuilder aib = ScriptOperators.accumulatorBuilder();
AccumulatorInitArgsBuilder aiab = aib.init("function() {return { count: 0, sum: 0 }}");
aib.lang("js");
AccumulatorAccumulateArgsBuilder aaab = aiab
.accumulate("function(state, score) { return {count: state.count + 1,sum: state.sum + score}}");
List<Object> bl = new LinkedList<Object>();
bl.add("$score");
AccumulatorMergeBuilder amb = aaab.accumulateArgs(bl);
AccumulatorFinalizeBuilder afb = amb.merge(
"function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}");
// Accumulator a=afbb.build();
Accumulator a = afb.finalize("function(state) {return (state.sum / state.count)}");
GroupOperation groupByNameAndAccumulator = group("name").accumulate(a).as("avgScore");
Aggregation aggregation = newAggregation(groupByNameAndAccumulator);
List<ResultAccumulator> results = mongoOperations
.aggregate(aggregation, mongoTemplate.getCollectionName(Game.class), ResultAccumulator.class)
.getMappedResults();
// AggregationResults<ResultAccumulator> result =
// mongoTemplate.aggregate(aggregation, "game", ResultAccumulator.class);
return results;
public class ResultAccumulator {
@Id
private String name;
private Float avgScore;
public ResultAccumulator() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getAvgScore() {
return avgScore;
}
public void setAvgScore(float avgScore) {
this.avgScore = avgScore;
}
}
[
{
"name": "Elizabeth",
"avgScore": 10.0
},
{
"name": "James ",
"avgScore": 8.333333
},
{
"name": "John",
"avgScore": 8.333333
}
]
I'm new in Spring-Data-MongoDB, I'm developing a method that performs MongoDB $accumulator operator in Spring-Data-MongoDB, but I don't know why my result on the $accumulator
field return null.
Now I'm populating the collection in MongoDB:
db.game.insertMany([
{ "_id" : 1, "name" : "John", "score" : 10},
{ "_id" : 2, "name" : "Elizabeth", "score" : 10},
{ "_id" : 3, "name" : "James ", "score" : 9},
{ "_id" : 4, "name" : "John", "score" : 5},
{ "_id" : 5, "name" : "Elizabeth", "score" : 10},
{ "_id" : 6, "name" : "John", "score" : 10},
{ "_id" : 7, "name" : "Elizabeth", "score" : 10},
{ "_id" : 8, "name" : "James ", "score" : 8 },
{ "_id" : 9, "name" : "James ", "score" : 8}])
This is the accumulator aggregation in MongoDB Server:
db.game.aggregate ([
{
$group :
{
_id : "$name",
avgScore:
{
$accumulator:
{
init: function() {
return { count: 0, sum: 0 }
},
accumulate: function(state, score) {
return {
count: state.count + 1,
sum: state.sum + score
}
},
accumulateArgs: ["$score"],
merge: function(state1, state2) {
return {
count: state1.count + state2.count,
sum: state1.sum + state2.sum
}
},
finalize: function(state) {
return (state.sum / state.count)
},
lang: "js"
}
}
}
}
])
This is the result of MongoDB that I'm trying to perform via Spring-Data-MongoDB:
{ "_id" : "Elizabeth", "avgScore" : 10 }
{ "_id" : "John", "avgScore" : 8.333333333333334 }
{ "_id" : "James ", "avgScore" : 8.333333333333334 }
This is the result of My RestController:
[
{
"name": "Elizabeth",
"avgScore": null
},
{
"name": "James ",
"avgScore": null
},
{
"name": "John",
"avgScore": null
}
]
this is the model Class
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="game")
public class Game {
@Id
private Integer _id;
private String name;
private Integer score;
public Game() {
super();
// TODO Auto-generated constructor stub
}
public int get_id() {
return _id;
}
public void set_id(Integer _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
}
This is the Service that performs the $accumulator
operator on accumulator method, but it returns null:
import java.util.LinkedList;
import java.util.List;
import com.project.ecommercemongo.aggregation.ResultAccumulator;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorAccumulateArgsBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorFinalizeBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorInitArgsBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorInitBuilder;
import org.springframework.data.mongodb.core.aggregation.ScriptOperators.Accumulator.AccumulatorMergeBuilder;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import org.springframework.stereotype.Service;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import com.project.ecommercemongo.model.Game;
import com.project.ecommercemongo.repository.GameRepository;
@Service
public class GameService {
@Autowired
GameRepository game;
@Autowired
MongoTemplate mongoTemplate;
@Autowired
private MongoOperations mongoOperations;
public List<Game> findAll() {
List<Game> list = game.findAll();
return list;
}
public List<ResultAccumulator> accumulator() {
AccumulatorInitBuilder aib = ScriptOperators.accumulatorBuilder();
AccumulatorInitArgsBuilder aiab = aib.init("function() {return { count: 0, sum: 0 }}");
aib.lang("js");
AccumulatorAccumulateArgsBuilder aaac = aiab
.accumulate("function(state, score) { return {count: state.count + 1,sum: state.sum + score}}");
List<Object> bl = new LinkedList<Object>();
bl.add("score");
AccumulatorMergeBuilder amb = aaac.accumulateArgs(bl);
AccumulatorFinalizeBuilder afb = amb.merge(
"function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}");
// Accumulator a=afbb.build();
Accumulator a = afb.finalize("function(state) {return (state.sum / state.count)}");
Document document = a.toDocument();
/*AggregationExpression expression = new AggregationExpression() {
@Override
public Document toDocument(AggregationOperationContext context) {
Document document1 = document;
return document1;
}
};
Document document2 = expression.toDocument();*/
GroupOperation groupByNameAndAccumulator = group("name").last(String.valueOf(document)).as("avgScore");
Aggregation aggregation = newAggregation(groupByNameAndAccumulator);
List<ResultAccumulator> results = mongoOperations
.aggregate(aggregation, mongoTemplate.getCollectionName(Game.class), ResultAccumulator.class)
.getMappedResults();
// AggregationResults<ResultAccumulator> result =
// mongoTemplate.aggregate(aggregation, "game", ResultAccumulator.class);
System.out.println(document);
System.out.println(results.toString());
return results;
}
}
This is the server that print the Document containing the accumulator operator,
2022-07-04 00:42:28.696 INFO 13784 --- [nio-8080-exec-2] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:1531}] to localhost:27118
Document{{$accumulator=Document{{init=function() {return { count: 0, sum: 0 }}, accumulate=function(state, score) { return {count: state.count + 1,sum: state.sum + score}}, accumulateArgs=[score], merge=function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}, lang=js, finalize=function(state) {return (state.sum / state.count)}}}}}
[com.project.mongo.aggregation.ResultAccumulator@37517d96, com.project.mongo.aggregation.ResultAccumulator@19e6b063, com.project.emongo.aggregation.ResultAccumulator@3d69a1a5]
this is the Result Class
import org.springframework.data.annotation.Id;
public class ResultAccumulator {
@Id
private String name;
private Double avgScore;
public ResultAccumulator() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getAvgScore() {
return avgScore;
}
public void setAvgScore(Double avgScore) {
this.avgScore = avgScore;
}
}
this is the Controller
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.project.ecommercemongo.aggregation.ResultAccumulator;
import com.project.ecommercemongo.model.Game;
import com.project.ecommercemongo.service.GameService;
@RestController
@RequestMapping("/game")
public class GameController {
@Autowired
GameService service;
@GetMapping("/find")
public List<Game> listAll() {
return service.findAll();
}
@GetMapping("/accumulator")
public List<ResultAccumulator> accumulator() {
return service.accumulator();
}
}
I don't know what I'm doing wrong, maybe the problem is in the Object Accumulator
.
Bye and thank you in advance!
Update
Now it work my mistake was on the method last in group,now i have changed to accumulate(Accumulator)
AccumulatorInitBuilder aib = ScriptOperators.accumulatorBuilder();
AccumulatorInitArgsBuilder aiab = aib.init("function() {return { count: 0, sum: 0 }}");
aib.lang("js");
AccumulatorAccumulateArgsBuilder aaab = aiab
.accumulate("function(state, score) { return {count: state.count + 1,sum: state.sum + score}}");
List<Object> bl = new LinkedList<Object>();
bl.add("$score");
AccumulatorMergeBuilder amb = aaab.accumulateArgs(bl);
AccumulatorFinalizeBuilder afb = amb.merge(
"function(state1, state2) {return {count: state1.count + state2.count,sum: state1.sum + state2.sum}}");
// Accumulator a=afbb.build();
Accumulator a = afb.finalize("function(state) {return (state.sum / state.count)}");
GroupOperation groupByNameAndAccumulator = group("name").accumulate(a).as("avgScore");
Aggregation aggregation = newAggregation(groupByNameAndAccumulator);
List<ResultAccumulator> results = mongoOperations
.aggregate(aggregation, mongoTemplate.getCollectionName(Game.class), ResultAccumulator.class)
.getMappedResults();
// AggregationResults<ResultAccumulator> result =
// mongoTemplate.aggregate(aggregation, "game", ResultAccumulator.class);
return results;
public class ResultAccumulator {
@Id
private String name;
private Float avgScore;
public ResultAccumulator() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getAvgScore() {
return avgScore;
}
public void setAvgScore(float avgScore) {
this.avgScore = avgScore;
}
}
[
{
"name": "Elizabeth",
"avgScore": 10.0
},
{
"name": "James ",
"avgScore": 8.333333
},
{
"name": "John",
"avgScore": 8.333333
}
]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论