MongoDB에서는 NOT과 AND 논리 연산을 함께 사용할 수 있습니다. 다만 MongoDB 셸에는 직접적인 NOT 연산자가 없기 때문에, 일반적으로 $ne(not equal) 연산자와 조합하여 구현합니다. 기본 문법은 아래와 같습니다.
NOT X AND NOT Y = NOT (X AND Y)
위 문법의 동작 원리를 살펴보면 다음과 같습니다.
- X와 Y가 모두 참(true)이면, 최종 결과는 거짓(false)이 됩니다.
- 피연산자 중 하나라도 거짓(false)을 반환하면, 최종 결과는 참(true)이 됩니다.
이는 드모르간 법칙(De Morgan's Law)에 따른 것으로, NOT (X AND Y)는 NOT X OR NOT Y와 논리적으로 동일합니다. 따라서 MongoDB에서는 $or 연산자와 $ne 연산자를 조합해 이 로직을 표현하게 됩니다.
예제 컬렉션 생성하기
먼저 예제에 사용할 컬렉션에 문서를 삽입하는 쿼리입니다.
> db.NotAndDemo.insertOne({"StudentName":"John","StudentCountryName":"US"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c98746a330fd0aa0d2fe4a8")
}
> db.NotAndDemo.insertOne({"StudentName":"John","StudentCountryName":"UK"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c987478330fd0aa0d2fe4a9")
}
> db.NotAndDemo.insertOne({"StudentName":"David","StudentCountryName":"AUS"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c987487330fd0aa0d2fe4aa")
}
> db.NotAndDemo.insertOne({"StudentName":"Chris","StudentCountryName":"UK"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9874ac330fd0aa0d2fe4ab")
}
> db.NotAndDemo.insertOne({"StudentName":"Chris","StudentCountryName":"US"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9874b7330fd0aa0d2fe4ac")
}
저장된 전체 문서 조회하기
find() 메서드를 사용해 컬렉션의 모든 문서를 출력하는 쿼리입니다.
> db.NotAndDemo.find().pretty();
위 쿼리는 다음과 같은 결과를 출력합니다.
{
"_id" : ObjectId("5c98746a330fd0aa0d2fe4a8"),
"StudentName" : "John",
"StudentCountryName" : "US"
}
{
"_id" : ObjectId("5c987478330fd0aa0d2fe4a9"),
"StudentName" : "John",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c987487330fd0aa0d2fe4aa"),
"StudentName" : "David",
"StudentCountryName" : "AUS"
}
{
"_id" : ObjectId("5c9874ac330fd0aa0d2fe4ab"),
"StudentName" : "Chris",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c9874b7330fd0aa0d2fe4ac"),
"StudentName" : "Chris",
"StudentCountryName" : "US"
}
NOT과 AND 로직을 함께 적용한 쿼리
이제 NOT과 AND가 결합된 형태, 즉 NOT (X AND Y)와 같은 의미인 NOT X OR NOT Y 조건을 실제로 적용해 보겠습니다. 아래 쿼리는 "학생 이름이 Chris가 아니거나, 학생 국가가 US가 아닌" 문서를 조회합니다.
> db.NotAndDemo.find({
... "$or": [
... {"StudentName": {"$ne": "Chris"}},
... {"StudentCountryName": {"$ne": "US"}}
... ]
... }).pretty();
위 쿼리 실행 시 다음과 같은 결과가 출력됩니다.
{
"_id" : ObjectId("5c98746a330fd0aa0d2fe4a8"),
"StudentName" : "John",
"StudentCountryName" : "US"
}
{
"_id" : ObjectId("5c987478330fd0aa0d2fe4a9"),
"StudentName" : "John",
"StudentCountryName" : "UK"
}
{
"_id" : ObjectId("5c987487330fd0aa0d2fe4aa"),
"StudentName" : "David",
"StudentCountryName" : "AUS"
}
{
"_id" : ObjectId("5c9874ac330fd0aa0d2fe4ab"),
"StudentName" : "Chris",
"StudentCountryName" : "UK"
}
결과를 보면 이름이 Chris이면서 국가가 US인 마지막 문서만 제외되고 나머지 네 개의 문서가 반환된 것을 확인할 수 있습니다. 이처럼 $or와 $ne를 조합하면 NOT AND(NAND)와 동일한 필터링 효과를 손쉽게 얻을 수 있습니다.