HOWTO · MongoDB

MongoDB에서 여러 조건이 있는 쿼리

이 지침 게시물은 MongoDB의 여러 조건에서 여러 문서를 찾고 쿼리하는 데 사용할 수 있는 연산자를 알려줍니다. $and 및 $or 연산자에 대해 간단히 설명합니다.

이 페이지의 내용

find()에 필터 문서를 전달하면 여러 조건으로 MongoDB를 조회할 수 있습니다. 기본적으로 같은 필터에 지정한 필드는 AND로 결합됩니다. 나열한 절 중 하나라도 일치하면 되는 경우에는 $or, 모든 절이 일치해야 하는 경우에는 $and, 한 필드에서 여러 등가 값을 찾을 때는 $in을 사용합니다.

MongoDB가 쿼리 조건을 결합하는 방식

쿼리 필터는 반환할 문서를 지정합니다. 예를 들어 db.inventory.find({ quantity: { $gt: 10 }, price: { $lt: 20 } })는 수량이 10보다 크고 그리고 가격이 20보다 낮은 inventory 문서를 찾습니다. MongoDB는 서로 다른 필드의 이 조건들을 암묵적으로 AND로 결합하므로, 이 경우 $and를 명시할 필요가 없습니다.

아래 셸 예제에서는 db.inventory에 다음 세 문서가 있다고 가정합니다. { item: "notebook", quantity: 30, price: 12 }, { item: "pen", quantity: 80, price: 20 }, { item: "folder", quantity: 80, price: 8 }입니다. 첫 번째 쿼리는 notebook과 folder를 찾습니다. 두 문서 모두 수량이 10보다 많고 가격이 20보다 낮기 때문입니다. pen의 가격은 20이므로 가격 조건에 맞지 않습니다. 필터에 필드를 더 추가해도 같은 규칙이 적용됩니다. 모든 조건이 일치해야 합니다. 따라서 모든 조건을 만족하는 문서를 찾을 때는 일반 필터부터 사용하는 것이 가장 명확합니다. 컬렉션의 문서와 일치하도록 필드 이름과 값을 지정하세요. MongoDB의 필드 이름은 대소문자를 구분합니다.

$or로 조건 중 하나라도 일치하는 문서 찾기

$or는 배열에 담긴 절 중 하나 이상과 일치하는 문서를 선택합니다. 예를 들어 db.inventory.find({ $or: [{ quantity: { $lt: 51 } }, { price: 20 }] })는 수량이 51보다 적거나 가격이 20과 같은 문서를 반환합니다. { price: 20 } 조건은 등가 비교이며, 가격이 20보다 낮다는 뜻이 아닙니다. 비교를 표현하려면 $lt 같은 연산자를 사용하세요.

다음은 조건 중 하나라도 일치하는 규칙을 간단히 보여 주는 로컬 예제입니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

inventory = [
    {"item": "notebook", "quantity": 30, "price": 12},
    {"item": "pen", "quantity": 80, "price": 20},
    {"item": "folder", "quantity": 80, "price": 8},
]
matched = [
    item["item"]
    for item in inventory
    if item["quantity"] < 51 or item["price"] == 20
]
print(matched)
['notebook', 'pen']

이 Python 코드는 로컬 Python 목록에 선택 규칙을 적용하며 MongoDB에 연결하지 않습니다. 출력에는 수량이 51보다 적은 notebook과 가격이 20인 pen이 나열됩니다. 위 MongoDB 셸 쿼리도 find()를 사용해 별도로 설명한 db.inventory 샘플에 같은 OR 규칙을 적용합니다.

$and로 모든 조건을 만족하는 문서 찾기

$and는 배열에 담긴 모든 절이 일치할 때만 문서를 선택합니다. 샘플 db.inventory 컬렉션에서 db.inventory.find({ $and: [{ quantity: { $gte: 20 } }, { price: { $lt: 15 } }] })는 수량이 20 이상이고 가격이 15보다 낮은 두 조건을 모두 요구합니다. 각 조건을 만족하는 notebook과 folder가 결과에 포함됩니다.

서로 다른 필드에 조건을 적용한다면 이에 해당하는 암묵적 AND 필터는 db.inventory.find({ quantity: { $gte: 20 }, price: { $lt: 15 } })입니다. 각 필드가 한 번씩만 나타날 때는 이처럼 짧은 형식을 사용하는 것이 좋습니다. 같은 필드에 여러 표현식을 결합해야 할 때는 db.inventory.find({ $and: [{ price: { $gte: 10 } }, { price: { $lte: 20 } }] })처럼 $and를 명시할 수 있습니다. 프로그램에서 필터를 조합할 때도 여러 조건을 묶어 명확히 표현하는 데 유용합니다.

오류가 발생할 수 있는 다른 절을 막기 위해 $and의 절이 순서대로 평가된다고 가정하지 마세요. 쿼리 표현식은 일치 여부를 판별하는 조건이지, 왼쪽에서 오른쪽으로 평가를 중단한다고 보장된 절차가 아닙니다.

인덱스와 연산자 제한

인덱스는 쿼리 성능에 영향을 줄 수 있지만, 특정 쿼리가 이점을 얻는지는 컬렉션과 인덱스, 쿼리에 따라 달라집니다. 자체 작업의 성능을 평가할 때 필터에 사용한 필드와 조건을 고려하세요. 이 문서에서는 특정 인덱스나 쿼리 계획을 권장하지 않습니다.

조건을 결합할 때 각 연산자의 역할을 구분하세요. $or는 대안을 표현하고, $and는 모든 절의 일치를 요구하며, 하나의 필터에 일반 필드를 여러 개 지정하면 이미 AND가 적용됩니다. 이 차이를 이해하면 쿼리 의미를 바꾸지 않는 논리 연산자를 불필요하게 덧붙이는 일을 피할 수 있습니다.

한 필드의 등가 조건에는 $in 선택하기

같은 필드에서 여러 등가 조건을 확인할 때는 그 필드를 $or에 반복하는 것보다 $in이 대개 간결합니다. 예를 들어 db.inventory.find({ price: { $in: [12, 20] } })는 가격이 12 또는 20인 notebook과 pen을 찾습니다.

대안이 서로 다른 필드에 적용되거나 수량 비교, 가격 조건처럼 등가 비교가 아닌 조건을 포함하면 $or를 사용하세요. 모든 조건이 일치해야 한다면 일반적인 다중 필드 필터를 사용합니다. 적절한 형식은 원하는 논리에 따라 결정됩니다. 절 중 하나라도 일치해야 하면 $or, 모든 절이 일치해야 하면 $and(흔히 암묵적으로 적용됨), 한 필드에서 나열한 등가 값 중 하나와 일치하면 $in을 사용합니다.