Hello there and welcome back! In the previous lessons, you were introduced to MongoDB query operators, which enable you to craft more complex queries. Specifically, you covered comparison operators like $gt
, $gte
, $eq
, and others. In this lesson, we'll focus on logical query operators, which allow you to combine multiple conditions to fine-tune your data retrieval. Let's dive in!
In MongoDB, logical query operators are used to filter data based on expressions that evaluate to true or false:
$and
: Matches documents where all conditions are true.$or
: Matches documents where at least one condition is true.$not
: Matches documents where the condition is not true.$nor
: Matches documents where none of the conditions are true.
The $and
operator combines multiple conditions and only matches documents where all conditions are met. Its syntax requires an array of objects, each representing a condition. Let's run the following command to find the comic books with genres including "Adventure" and featuring Spider-Man as one of the characters:
JavaScript1use comic_book_store_db 2 3db.comic_books.find( 4 { $and: [ { genres: "Adventure" }, { "characters.name": "Spider-Man" } ] }, 5 { title: 1, genres: 1, _id: 0 } 6).pretty()
Looks a little bit bulky, right? Actually, the $and
operator is the default in a MongoDB filter object, so you can omit it to simplify the expression, like so:
JavaScript1use comic_book_store_db 2 3db.comic_books.find( 4 { genres: "Adventure", "characters.name": "Spider-Man" }, 5 { title: 1, genres: 1, _id: 0 } 6).pretty()
So why do we need the $and
operator at all? Let's imagine we want to use the same field for querying. For example, suppose we want to find comic books that contain both "Sci-Fi" and "Mystic" genres:
JavaScript1use comic_book_store_db 2 3db.comic_books.find( 4 { genres: "Sci-Fi", genres: "Mystic" }, 5 { title: 1, genres: 1, _id: 0 } 6).pretty()
This query will give you the wrong result because JSON objects don't allow duplicate fields; it will simply override the earlier value with the latter value. In this specific example, { genres: "Sci-Fi", genres: "Mystic" }
will be equivalent to { genres: "Mystic" }
. This is where the $and
operator comes to the rescue:
JavaScript1use comic_book_store_db 2 3db.comic_books.find( 4 { $and: [ { genres: "Sci-Fi" }, { genres: "Mystic" } ] }, 5 { title: 1, genres: 1, _id: 0 } 6).pretty()
This query will correctly find all comic books that belong to both Sci-Fi and Mystic genres. There are no such comics in our collection, by the way.
The $or
operator retrieves documents where at least one of the specified conditions is true. To illustrate, let's use the $or
operator to find comic books that are either very old (published before 1970) or very new (published after 2000). Here’s the query:
JavaScript1use comic_book_store_db 2 3db.comic_books.find( 4 { $or: [ { published_year: { $lt: 1970 } }, { published_year: { $gt: 2000 } } ] }, 5 { title: 1, published_year: 1, _id: 0 } 6).pretty()
As you can see, its syntax is similar to the $and
operator, requiring an array of objects, each representing a condition.
The $nor
operator is just the opposite of the $or
operator, it retrieves documents where none of the conditions are true. In essence, they retrieve different parts of the collection based on the specified conditions. Let's replace the $or
operator with $nor
in the following code snippet, like so:
mongo1use comic_book_store_db 2 3db.comic_books.find( 4 { $nor: [ { published_year: { $lt: 1970 } }, { published_year: { $gt: 2000 } } ] }, 5 { title: 1, published_year: 1, _id: 0 } 6).pretty()
It will simply retrieve us all the comic books which are neither old, nor new and were published between 1970 and 2000.
Last but not least, the $not
operator! The $not
operator matches documents where the condition is not true. If we want to find a comic book in our comic_book_store_db
that was not written by Jack Kirby, we would use:
JavaScript1use comic_book_store_db 2 3db.comic_books.findOne( 4 { "writer.name": {$not: {$eq: "Jack Kirby"} } }, 5 { title: 1, "writer.name": 1, _id: 0 } 6)
There are a few important syntax considerations with the $not
operator. Firstly, it shouldn't be at the top level of the query like this:
- Incorrect:
{ $not: { genres: "Horror" } }
- Fixed:
{ genres: { $not: { $eq: "Horror" } } }
Additionally, its value should always be an object:
- Incorrect:
{ published_year: { $not: 1995 } }
- Fixed:
{ published_year: { $not: { $eq: 1995 } } }
So be mindful of the syntax.
Great job on making it through this lesson! Today, we explored logical query operators in MongoDB and used $and
, $or
, $not
, and $nor
to refine our data retrieval. Keep practicing using these operators until they become second nature. Our next steps? Applying these concepts in the practice exercises that follow this lesson.