MongoDB에서 배열 요소가 특정 단어의 부분 문자열인 문서 찾기
배열 내 문자열 중 하나라도 특정 단어의 부분 문자열(substring)에 해당하는지 확인하려면 MongoDB의 aggregate() 메서드를 활용해야 합니다. 이 방식은 $match, $expr, $map, $indexOfBytes 등의 연산자를 조합하여 배열의 각 요소를 유연하게 검사할 수 있습니다.
1. 샘플 컬렉션 생성 및 문서 삽입
먼저 데모용 컬렉션을 만들고 문서를 삽입해 보겠습니다.
> db.demo90.insertOne(
... {"words": ["john", "jace"]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2c1ada79799acab037af56")
}
> db.demo90.insertOne(
... {"words": ["sam", "adam"]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2c1adb79799acab037af57")
}2. find()로 전체 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.
> db.demo90.find();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e2c1ada79799acab037af56"), "words" : [ "john", "jace" ] }
{ "_id" : ObjectId("5e2c1adb79799acab037af57"), "words" : [ "sam", "adam" ] }3. 부분 문자열 조건으로 문서 조회하는 쿼리
아래는 words 배열의 요소 중 하나라도 특정 단어(예: "john")의 부분 문자열에 해당하는 문서만 필터링하는 쿼리입니다. $map으로 배열의 각 요소를 순회하고, $indexOfBytes로 해당 단어 안에서 요소의 위치를 찾습니다. 결과가 -1이 아니라면 부분 문자열로 존재한다는 의미이며, $anyElementTrue가 하나라도 일치하는 요소가 있는지 판단합니다.
> db.demo90.aggregate([ { $match: { $expr: { $anyElementTrue: { $map: { input: "$words", as: "j", in: { $ne: [ -1, { $indexOfBytes: [ "john", "$$j" ] } ] } } } } } } ]);쿼리 실행 결과는 다음과 같습니다. "john"이라는 단어의 부분 문자열에 해당하는 요소("john")를 가진 첫 번째 문서만 반환된 것을 확인할 수 있습니다.
{ "_id" : ObjectId("5e2c1ada79799acab037af56"), "words" : [ "john", "jace" ] }핵심 정리
이 기법의 핵심은 다음과 같습니다.
- $expr: 집계 표현식을 일반 쿼리 조건처럼 사용할 수 있게 해줍니다.
- $map: 배열의 각 요소를 개별적으로 검사할 수 있습니다.
- $indexOfBytes: 검색 대상 문자열에서 부분 문자열의 시작 위치를 반환하며, 없으면 -1을 반환합니다.
- $anyElementTrue: 배열 조건 중 하나라도 참이면 true를 반환합니다.
이러한 조합을 활용하면 MongoDB에서 배열 필드와 문자열 간의 복잡한 포함 관계 조건도 손쉽게 처리할 수 있습니다.