Руководство Spring-boot + Mongodb не работает, не могу найти свою ошибку, запрос Mongodb работает нормально

Я новичок в 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

Почтальон

GET findAll показывает:

[{id:5f56021d61738cc35de79438,name:Romeo,entryDate:[2020,8,24],game:null},{id:5f5602e361738cc35de79439,name:Julieta,entryDate:[2020,8,24],game:null}, . ...]

показана игра, потому что я добавил также геттеры и сеттеры для этого свойства, просто пытаясь найти способ правильно отображать игры как ручные ссылки на игроков

ПОЛУЧИТЬ findВсе игры:

[{id:5f5614a361738cc35de7943b,кубики:{value1:1,value2:6},gameScore:1,playerId:5f56021d61738cc35de79438},

{id: 5f5619f561738cc35de7943c, кубики: {value1: 2, value2: 5}, gameScore: 1, playerId: 5f5602e361738cc35de79439},

{id:5f561a5461738cc35de7943d,dices:{value1:3,value2:3},gameScore:0,playerId:5f56021d61738cc35de79438}, ...]

GET lh:8080/players/5f56021d61738cc35de79438/games дает пустой массив, поэтому я предполагаю, что сопоставление между коллекциями в Spring-boot не выполняется.

Репозиторий игр

@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));
    }

Советы приветствуются!


person kekamv    schedule 09.09.2020    source источник


Ответы (1)


Агрегации не работают с MongoRepostory, если вы не используете @DBRef. Но использовать @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();
}
person varman    schedule 09.09.2020
comment
Извините, я удалил свой предыдущий комментарий. Если я правильно понимаю, я должен добавить следующие bean-компоненты в класс конфигурации: ```` public @Bean MongoClient mongoClient() { return MongoClients.create(connectionString); } public @Bean MongoTemplate mongoTemplate() { return new MongoTemplate((com.mongodb.MongoClient) mongoClient(), dicesdb); } ``` - person kekamv; 11.09.2020
comment
Я не использую клиент mongo, так как mongoTemple включает его. Какова ваша зависимость от mongodb - person varman; 11.09.2020
comment
Спасибо @varman! вы правы, это была моя ошибка, я пытался подключить MongoTemplate к интерфейсу... :/upsss. Я нашел дальнейшие шаги в этом вопросе: stackoverflow.com/questions/38288258/ - person kekamv; 11.09.2020
comment
@kekamv, если этот ответ поможет вам, пожалуйста, нажмите на голосование и примите ответ, который поможет людям, которые ищут такого рода проблемы. - person varman; 21.09.2020