MongoDB에 대해서 알기전에 Nosql이 뭔지 알고 넘어가도록 하자!
Local환경에서 mongoDB를 실행하기 위해서는 설치를 받아야 합니다.
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
@Data
@Document(collection = "chat")
public class Chat {
@Id
private String id;
private String msg;
private String sender; // 보내는 사람
private String receiver; // 받는 사람 (귓속말)
private Integer roomNum; // 방 번호
private LocalDateTime createdAt;
}
@RequiredArgsConstructor
@RestController
public class ChatController {
private final ChatRepository chatRepository;
@CrossOrigin
@GetMapping(value = "/sender/{sender}/receiver/{receiver}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Chat> getMsg(@PathVariable String sender, @PathVariable String receiver) {
return chatRepository.mFindBySender(sender, receiver)
.subscribeOn(Schedulers.boundedElastic());
}
@CrossOrigin
@GetMapping(value = "/chat/roomNum/{roomNum}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Chat> findByRoomNum(@PathVariable Integer roomNum) {
return chatRepository.mFindByRoomNum(roomNum)
.subscribeOn(Schedulers.boundedElastic());
}
@CrossOrigin
@PostMapping("/chat")
public Mono<Chat> setMsg(@RequestBody Chat chat){
chat.setCreatedAt(LocalDateTime.now());
return chatRepository.save(chat); // Object를 리턴하면 자동으로 JSON 변환 (MessageConverter)
}
}
public interface ChatRepository extends ReactiveMongoRepository<Chat, String> {
@Tailable
@Query("{ sender : ?0, receiver : ?1}")
Flux<Chat> mFindBySender(String sender, String receiver); // Flux (흐름) response를 유지하면서 데이터를 계속 흘려보내기
@Tailable
@Query("{ 'roomNum': ?0 }")
Flux<Chat> mFindByRoomNum(Integer roomNum);
}
커서를 닫지 않고 계속 유지하고 최신 DB 내용을 변환하게 되는 @Tailable 어노테이션을 추가하면 Flux를 통해서 데이터가 게속 흘러들어오게 되므로 새로 추가된 데이터를 변환합니다.
postMan을 이용하여 통신
mongoDB에 잘 저장되는 것을 확인할 수 있습니다.
2023-08-16T16:33:25.545+09:00 ERROR 10340 --- [ntLoopGroup-3-3] a.w.r.e.AbstractErrorWebExceptionHandler : [2cad4529-1] 500 Server Error for HTTP GET "/chat/roomNum/1"
org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 2 (BadValue): 'error processing query: ns=chatdb.chat batchSize=2Tree: roomNum $eq 1
Sort: {}
Proj: {}
tailable cursor requested on non capped collection' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "error processing query: ns=chatdb.chat batchSize=2Tree: roomNum $eq 1\nSort: {}\nProj: {}\n tailable cursor requested on non capped collection", "code": 2, "codeName": "BadValue"}
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:140) ~[spring-data-mongodb-4.1.2.jar:4.1.2]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ Handler com.ll.mongoChat.ChatController#findByRoomNum(Integer) [DispatcherHandler]
*__checkpoint ⇢ HTTP GET "/chat/roomNum/1" [ExceptionHandlingWebHandler]
tailable cursor가 capped collection이 아닌 컬렉션에서 요청되었음을 의미
-> Tailable cursor는 capped collection에서만 사용할 수 있음
-> Capped collection은 MongoDB에서 고정된 크기를 갖는 특수한 타입의 컬렉션
해결방법
1, mongoDB Shell 다운로드 (https://www.mongodb.com/try/download/shell)
2, 받은 폴더 -> bin -> monosh.exe 실행
3, 현재 설정한 DB 포트로 접속
4, 해당 데이터베이스로 이동
5, convertToCapped 명령어 입력
-> db.runCommand( { convertToCapped: 'chat', size: 8192 } )
6, 적용 여부 확인 ( capped: true로 되어있으면 성공 )