몽고DB에서 제공하는 watch 함수를 사용하면 트리거를 만들 수 있습니다.
몽고DB는 트리거(trigger)를 제공하지 않기 때문에 관계형 데이터베이스처럼 데이터의 변화에 따른 행동을 정의하기가 다소 불편했던 것은 사실 입니다
* 2022년 1월 기준
몽고db에서는 컬렉션 객체에서 watch 함수를 지원 합니다.
https://docs.mongodb.com/manual/reference/method/db.collection.watch/
watch 함수는 바라보고 있는 컬렉션에 대한 변화를 감지하여 정의해 둔 콜백함수에 내용을 전달하게 되어 있습니다.
마찬가지로 Java에서 주로 사용되는 Mongotemplate를 사용하면 쉽게 watch메소드(함수)를 사용할 수 있습니다.
먼저 Mongotemplate 객체에서 컬렉션 값을 가져 옵니다.
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
public class 몽고DB_WATCH_TEST {
public MongoTemplate template;
public void test(){
MongoCollection<Document> collection = template.getCollection("바라볼컬렉션");
}
}
가져온 컬렉션 값에서 watch 메소드를 호출합니다.
watch 메소드는 Iterable 인터페이스를 상속 받고 있습니다.
그러므로 해당 메소드에서 hasNext와 next 메소드를 호출하여 반복문을 돌려 줍니다.
그러면 ChangeStreamDocument 라는 클래스를 만날 수 있습니다.
해당 클래스에는 바라보는 컬렉션의 변화된 내용이 담겨 있습니다.
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.changestream.ChangeStreamDocument;
public class 몽고DB_WATCH_TEST {
public MongoTemplate template;
public void test(){
MongoCollection<Document> collection = template.getCollection("바라볼컬렉션");
MongoCursor<ChangeStreamDocument<Document>> cursor = collection.watch().iterator();
while(cursor.hasNext()) {
ChangeStreamDocument<Document> item = cursor.next();
}
}
}
그런데 해당 기능에서의 조금 아쉬운 점은 발행(publish)과 구독(subscribe) 형태의 기능으로 개발되어 있지 않기 때문에 반복문인 while 명령어를 실행하면 thread 전체가 멈춘다는 것 입니다.
그러므로 별도의 스레드(thread)를 만들어서 실행하여 줍니다.
이때 대표적인 값 2개를 출력하여 보겠습니다.
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.changestream.ChangeStreamDocument;
public class 몽고DB_WATCH_TEST {
public MongoTemplate template;
public void test(){
MongoCollection<Document> collection = template.getCollection("바라볼컬렉션");
MongoCursor<ChangeStreamDocument<Document>> cursor = collection.watch().iterator();
new Thread(()->{
while(cursor.hasNext()) {
ChangeStreamDocument<Document> item = cursor.next();
System.out.println(item.getFullDocument()); //변화된 도큐먼트 전체 값들
System.out.println(item.getOperationType()); //변화된 타입
System.out.println("");
}
}).start();
}
}
요렇게 하고나면 이제 등록, 수정, 삭제를 한번 해 보겠습니다.
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.MongoTemplate;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.changestream.ChangeStreamDocument;
public class 몽고DB_WATCH_TEST {
public MongoTemplate template;
private static final String 바라볼컬렉션 = "targetCollection";
public void test(){
MongoCollection<Document> collection = template.getCollection(바라볼컬렉션);
MongoCursor<ChangeStreamDocument<Document>> cursor = collection.watch().iterator();
new Thread(()->{
while(cursor.hasNext()) {
ChangeStreamDocument<Document> item = cursor.next();
System.out.println("등록시 : "+item.getFullDocument());
System.out.println("수정시 : "+item.getUpdateDescription());
System.out.println("아이디 : "+item.getDocumentKey());
System.out.println("작업형태 : "+item.getOperationType());
System.out.println("");
}
}).start();
//#0. 위 watch 함수가 정상적으로 동작하기 위해 잠시 1초간 멈춤니다
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
//#1. 등록
Document doc = new Document();
doc.put("text", "hello world");
doc.put("number", 5678);
template.insert(doc, 바라볼컬렉션);
//#2. 수정
Query query = new Query();
query.addCriteria(Criteria.where("number").is(5678));
Update update = new Update();
update.set("test", "change");
template.updateFirst(query, update, 바라볼컬렉션);
//#3. 삭제
template.remove(query , 바라볼컬렉션);
}
}
등록, 수정, 삭제 행동을 달아보았습니다.
해당 클래스를 실행하면 아래와 같은 결과가 나옵니다.
getOperationType메소드를 활용하면 등록을 하는경우에 insert가 나오고, 수정하면 update, 삭제하면 delete 값이 나오는 것을 볼 수 있습니다.
여기에 사용자가 원하는 기능을 붙이면 훌륭한 트리거 기능이 완성 됩니다.
일반적으로 JPA 기능을 사용하는 분 들 이라면..사실 이러한 세부적 기능을 만들기가 쉽지가 않습니다.
구글링을 하여도 관련된 글을 찾기가 무척 어려웠던거 같습니다. -_ㅜ
이상으로 Watch 함수를 통한 몽고DB 트리거(mongoDB watch trigger)에 대해서 살펴보았습니다.
궁금한점 또는 틀린 부분은 언제든 연락주세요!👻
'몽고DB > Java 몽고DB' 카테고리의 다른 글
Mongodb Aggregate 밀리세컨드(milliseconds) 변환(날짜, 문자형식) with Mongotemplate (5) | 2021.07.07 |
---|---|
몽고DB Aggregate 를 병렬 동작 처럼(Mongodb aggregate facet) (0) | 2020.11.03 |
몽고 db에서의 특수문자 검색(Mongodb 특수문자)시 유의사항 (0) | 2020.07.29 |
Java 몽고DB 파일 업로드 (Java mongodb file, Java mongodb fs) (0) | 2020.07.03 |
MongoTemplate or연산자를 통한 질의문 만들기(MongoTemplate or query) (0) | 2020.06.18 |
댓글