问题描述
我是Spring-boot和MongoDB的新手。在MongoDB中,两个集合之间的手动引用可以正常工作。 Spring-boot中的映射似乎不起作用。我真的不知道还要检查什么。在所有相关的详细信息下面,很长的问题对不起。
不使用DBref的原因是因为我可能需要这些投影。
“玩家”集合具有此架构(不允许其他任何形式)
{"_id":{"$oid":"5f56021d61738cc35de79438"},"name":"Romeo","entryDate":{"$date":"2020-08-23T22:00:00.000Z"}}`
“游戏”集合具有以下架构
{
"_id":{"$oid":"5f5614a361738cc35de7943b"},"dices":{
"value1":1,"value2":6
},"gamescore":1,"player_id":{"$oid":"5f56021d61738cc35de79438"}
}
MongoDB Compass中的聚合
[{
$match: {
_id: ObjectId('5f56021d61738cc35de79438')
}
},{
$lookup: {
from: 'games',localField: '_id',foreignField: 'player_id',as: 'games'
}
}]
收益
在Spring-boot中,POJO为:
@Document(collection = "players")
public class Player {
@Id
private String id;
private String name;
private LocalDate entryDate= LocalDate.Now();
private List<Game> game;
public Player(){};
public Player(String name) {
this.name = name;
}
//getters and setters for all properties,including game
}
@Document(collection = "games")
public class Game {
@Id
private String id;
private Dices dices;
private Integer gamescore;
@Field(value = "player_id")
private String playerId;
public Game(){};
public Game(Dices dices) {
this.dices = dices;
}
//getters and setters for all properties
}
public class Dices {
private int value1;
private int value2;
public Dices(){}
public Dices(int value1,int value2) {
this.value1 = value1;
this.value2 = value2;
}
//getters and setters for both properties
在邮递员中
[{“ id”:“ 5f56021d61738cc35de79438”,“名称”:“ Romeo”,“ entryDate”:[2020,8,24],“ game”:null},{“ id”:“ 5f5602e361738cc35de79439”,“ name“:” Julieta“,” entryDate“:[2020,24],” game“:null}, ....]
显示游戏是因为我还为此属性添加了getter和setter方法,只是试图找到一种方法来正确映射游戏作为对玩家的手动引用
获取findAll游戏:
[{“ id”:“ 5f5614a361738cc35de7943b”,“ dices”:{“ value1”:1,“ value2”:6},“ gamescore”:1,“ playerId”:“ 5f56021d61738cc35de79438”},
{“ id”:“ 5f5619f561738cc35de7943c”,“骰子”:{“ value1”:2,“ value2”:5},“ gamescore”:1,“ playerId”:“ 5f5602e361738cc35de79439”},
{“ id”:“ 5f561a5461738cc35de7943d”,“骰子”:{“ value1”:3,“ value2”:3},“ gamescore”:0,“ playerId”:“ 5f56021d61738cc35de79438”}, ...]
GET lh:8080 / players / 5f56021d61738cc35de79438 / games 产生一个空数组,这就是为什么我认为Spring-boot中的集合之间的映射失败的原因。
GamesRepository
@Repository
public interface GameRepository extends MongoRepository<Game,String> {
List<Game> findAll();
List<Game> findGamesByPlayerId(String playerId);
}
服务中的方法
@Override
public List<Game> findAllGamesByPlayerId(String playerId) {
Optional<Player> playerDB= playerRepository.findById(playerId);
if(playerDB.isPresent()) {
return gameRepository.findGamesByPlayerId(playerId);
}
else throw new ResourceNotFoundException("Player with id: "+playerId+" does not exist");
}
和GameController
@GetMapping("/{ID}/games")
public ResponseEntity<List<Game>> getAllGamesByPlayerId (@PathVariable("ID") String playerId){
return ResponseEntity.ok()
.body(gameService.findAllGamesByPlayerId(playerId));
}
欢迎小贴士!
解决方法
除非您使用@DBRef,否则汇总不适用于MongoRepostory。但是不建议使用@DBRef
。您在聚合中所做的工作可以转换为Spring数据的聚合管道。
为此,您需要自动连接MongoTemplate
@Autowired
MongoTemplate mongoTemplate;
然后,您可以转换您编写的聚合。我尚未测试过,因为您的汇总正在运行,所以应该可以。
public List<Object> test(ObjectId id){
Aggregation aggregation = Aggregation.newAggregation(
match(Criteria.where("_id").is(id)),lookup("games","_id","player_id","games")
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation,mongoTemplate.getCollectionName(Players.class),Object.class).getMappedResults();
}