<아랑고DB> 6. AQL(Arango Query Lang) 배워보기 3 - REPLACE / UPSERT / REMOVE
14 Nov 2021 | 아랑고DB 그래프DB1. REPLACE, UPSERT, REMOVE
REPLACE
UPDATE가 _key값이 일치하는 도큐먼트의 일부분을 바꾸었다면 REPLACE는 도큐먼트 자체를 바꾸는 연산을 한다.
문법도 UPDATE와 동일하다. _key값이 포함된 도큐먼트를 전달해 한 번에 바꾸거나, _key값을 먼저 지정해주고, 이후에 도큐먼트를 전달하는 방식이다.
- REPLACE document IN collection
- REPLACE keyExpression WITH document IN collection
나머지 방식이나 Options 같은 경우도 UPDATE와 동일하기 때문에 건너뛴다. UPDATE에 관한 이전 글은 여기를 보면 됨
REMOVE
UPSERT 전에 쉬운 REMOVE 먼저 잠깐 살펴본다. 이름 그대로 도큐먼트를 제거하는 연산이며, keyExpression 을 사용한다. 즉, _key값을 기준으로 제거할 도큐먼트를 찾는다.
아래 문법처럼 사용하며, 간단하니까 얘도 생략한다.
- REMOVE keyExpression IN collection
UPSERT
마지막으로 볼 연산자는 UPSERT라는 재미있는 연산이다. UPSERT는 UPDATE와 INSERT의 합성어로써 아래 두 가지 상황에 맞는 동작을 한다.
- 데이터가 없으면 INSERT를 한다.
- 데이터가 이미 존재하면 UPDATE나REPLACE를 한다.
문법은 아래 두 가지 형태를 취한다.
- UPSERT searchExpression INSERT insertExpression UPDATE updateExpression IN collection
- UPSERT searchExpression INSERT insertExpression REPLACE updateExpression IN collection
여기서 주목해야할 점은 keyExpression 을 통해 _key를 기준으로하는 UPDATE 연산과 달리, UPSERT는 searchExpression 을 기준으로 삼는다는 점이다. 이는 아래 세 가지 포인트를 갖는다.
- _key값에 국한되지 않고 여러 필드로 조건을 걸 수 있다!
- 동시에, _key는 고유했지만 필드는 고유하지 않을 수 있기에 여러 도큐먼트가UPSERT의 대상이 될 수 있다
- 그리고 그들 중 하나가 임의로 대상 지정된다
이제 실제 연산을 실행해보자. 컬렉션에 관한 설정은 여기에서 CREATE 부분의 노란 박스를 보면 됨.
titles 컬렉션의 인덱스 설정은 그대로 둔 채, 데이터만 truncate 해주자.
// 빈 컬렉션에 해리포터 시리즈를 7편 넣어준다
FOR i in 1..7
  INSERT {
      'title': CONCAT('Harry Potter ', i), 
      'series': 'Harry Potter'
  } INTO titles// 이제 해리포터 시리즈에 UPSERT 연산을 해보자
// 임의의 해리포터 도큐먼트(총 7개) 중 하나에 `series_num`이라는 필드가 추가되었다
UPSERT {'series': 'Harry Potter'}
  INSERT {'meaning': 'less'}
  UPDATE {'series_num': 1}
INTO titles// 이번에는 없는 도큐먼트에 대해 UPSERT를 해보자
UPSERT {'series': 'Avengers'}
  INSERT {'meaning': 'less'}
  UPDATE {'series_num': 1}
INTO titles위 연산은 대상 도큐먼트가 없기 때문에 INSERT 연산을 수행하게 되어 새로운 도큐먼트를 만든다.
그럼 위 연산을 한 번 더 실행하면 어떻게 될까? 지금 생각으로는 또다른 {‘meaning’: ‘less’} 도큐먼트를 삽입할 것 같다.
직접 해보자
// 원모어타임
UPSERT {'series': 'Avengers'}
  INSERT {'meaning': 'less'}
  UPDATE {'series_num': 1}
INTO titlestitle 필드에 고유 인덱스 설정을 잘 주었다면, 위 AQL은 오류를 일으킨다. title은 반드시 unique해야 하는데, {‘meaning’: ‘less’} 도큐먼트는 ‘title’을 null값으로 가지고 있는 도큐먼트이기 때문이다.
따라서 해당 도큐먼트를 2개 넣으면 null이 두 개가 되어 고유값 에러를 일으킨다. 재미있는 발견이다.
UPSERT는 매우 유용한 기능이지만, 위와 같이 사용에 주의해야할 점들이 존재한다. 또한, UPSERT는 아랑고DB에서 HTTP API를 제공해주지 않는 연산 중 하나이다. 나머지 연산들은 모두 API가 열려있지만, UPSERT만은 AQL을 통해서만 수행이 가능하다.
이는 많은 아랑고 유저들이 개선을 원하는 부분 중 하나인데 아직까지 해결되고 있지는 않다. 깃헙 이슈 참고.
2. CRUD Best Practice
AQL 기초 1~3편을 통해 기초 연산들을 배워보았다. 그럼 언제 어느 연산을 사용해야 할까?
데이터를 넣고, 업데이트하는 몇가지 상황을 생각해보자.
데이터를 넣을건데, (영화명, 영화시리즈번호)의 쌍이 고유했으면 좋겠다.
이 경우는 이때까지 예제로 살펴봤던 것과 약간 다르게, 여러 개의 필드쌍이 하나의 _key를 구성해야 하는 경우이다.
여러 방법이 있는데, 1) index에 컴마로 분리하여 두 개 필드를 넣어 unique 제한을 주거나 2) 애초에 _key값을 영화명_영화시리즈번호로 만들어 넣는 것이다.
나는 후자의 방법이 가장 빠른 시스템 인덱스인 _key를 사용하고, 별도의 추가 인덱스를 생성하지 않기 때문에 선호하는 편이다.
이렇게 인덱스를 설정한 후, INSERT로 ignoreErrors:true, overWrite:ignore 를 줘서 빠르게 밀어넣는다.
시간별 통계 데이터를 넣을건데, 10분마다 업데이트되는 값을 반영하고싶다.
예를 들어, 시간별 블로그 이용자 통계를 만들고 싶다고 가정해보자. 이 통계의 업데이트 주기가 10분이라면 15시 데이터에 대해, 15시 10분에 측정한 값과 15시 20분에 측정한 값은 다를 것이다. (10분동안 사람들이 더 들어왔을거니까)
그럼 나는 {시간 : ‘2021-11-14-15’} 인 도큐먼트가 없으면 넣어주고, 있으면 업데이트를 하고 싶다.
없으면 넣어주고 있으면 업데이트하는 편리한 연산을 우리는 방금 배웠다. 이런 경우에 UPSERT - REPLACE를 쓰면 된다. 1번과 마찬가지로 시간값을 _key로 만들어주는게 쿼리 튜닝에 좋다.
왜 UPSERT - UPDATE가 아니고 REPLACE를 썼을까? 단순히 통계값이 방문자수 하나이면 UPDATE가 간편하지만, 통계값이 무수히 많다면 REPLACE 하나로 전체 도큐먼트를 통째로 교체하는게 낫다.
아니면, 앞서 배운 INSERT의 OPTIONS가 기억나는가? 얘를 써도 좋다.
두 연산이 완전히 동일한 것인지에 대한 의문이 드는데, 이 부분은 Arango Community에 질문 후 답변이 오면 여기에 수정해두도록 하겠다.
===
2021년 11월 24일 추가) 까먹고 있다가 오늘 질문을 해서 관련 답변을 받았다. 결론은 여기에 매우 자세하게 나와있다.
핵심만 말하면, 아래의 경우일 때, INSERT와 UPSERT는 거의 동일한 연산이라고 볼 수 있다.
- _key를 사용하여 탐색할 경우
- 그리고 RETURN OLD와 같이 기존 데이터를 참조하는 표현을 쓰지 않는 경우
그럼에도, INSERT가 훨씬 효율이 좋다. 그리고 REST API를 사용하면 효율이 더더욱 좋다.
===
3. 어디까지 왔나
이제 기초적인 CRUD에 관한 AQL은 다 다룬 것 같다. 나중에 기회가되면 부록처럼 각 연산의 원리와 성능에 대해 추가적으로 적어보려고 한다.
다음 시간부터는 AQL의 꽃인 그래프 관련 연산을 살펴본다. 그래프 횡단부터 시작하여, 각 횡단 단계에서 실행할 수 있는 여러가지 연산들을 배워보자.
아~주 재미있는 시간이 될 것이다. 기대해도 좋다 :)
- 아랑고DB란? 왜 쓰는가?
- 아랑고DB 세팅하기 on Ubuntu
- 아랑고DB 쉘로 붙어서 명령어 체험해보기, 실체 파악해보기
- AQL(Arango Query Lang) 배워보기 1
- AQL(Arango Query Lang) 배워보기 2 - RETURN / UPDATE
- (지금 보고있는 글) AQL(Arango Query Lang) 배워보기 3 - REPLACE / UPSERT / REMOVE
- 그래프 개념잡기
- 그래프 횡단하기 Graph Traversal
- 데이터 모으기 COLLECT / AGGREGATE / MIN_BY, MAX_BY
- 프로젝트. 그래프를 통한 영화 추천시스템 만들어보기 1
- 프로젝트. 그래프를 통한 영화 추천시스템 만들어보기 2 (최종편)
