5. Filtering documents

You already know how to do basic queries with exact filters. Now you will learn more powerful operators for filtering data.

Comparison operators

Comparison operators work similarly to SQL:

  • $eq: equal to
  • $ne: not equal to
  • $gt: greater than
  • $gte: greater than or equal to
  • $lt: less than
  • $lte: less than or equal to
// Unicorns with more than 100 vampires
db.unicorns.find({ vampires: { $gt: 100 } })

// Unicorns with 50 vampires or fewer
db.unicorns.find({ vampires: { $lte: 50 } })

// Unicorns that are NOT male
db.unicorns.find({ gender: { $ne: 'm' } })

Logical operators

To combine conditions:

Implicit AND (separating with commas):

db.unicorns.find({
    gender: 'f',
    weight: { $gt: 400 }
})

Explicit OR (with $or):

db.unicorns.find({
    $or: [
        { weight: { $lt: 500 } },
        { vampires: { $gt: 100 } }
    ]
})

Combining AND and OR:

db.unicorns.find({
    gender: 'f',
    $or: [
        { weight: { $lt: 500 } },
        { vampires: { $lt: 50 } }
    ]
})

The $in operator

To search for values in an array:

// Unicorns from Madrid or Barcelona
db.users.find({
    city: { $in: ['Madrid', 'Barcelona'] }
})

The $nin operator is the opposite (not in):

db.users.find({
    city: { $nin: ['Madrid', 'Barcelona'] }
})

Searching in arrays

MongoDB treats arrays in a special way. If a field is an array, you can search whether it contains a value:

// Unicorns that love carrots
db.unicorns.find({ loves: 'carrot' })

This works even if loves is an array. MongoDB searches whether 'carrot' is in the array.

To search for documents with specific values in arrays:

// Unicorns that love apples OR oranges
db.unicorns.find({
    loves: { $in: ['apple', 'orange'] }
})

Partial text searches (equivalent to LIKE)

In SQL you use LIKE to search for text patterns. In MongoDB you use $regex for regular expressions.

Basic search

// SQL: WHERE name LIKE 'Aurora%'
// MongoDB: names that start with "Aurora"
db.unicorns.find({ name: { $regex: /^Aurora/ } })

// SQL: WHERE name LIKE '%horn%'
// MongoDB: names that contain "horn"
db.unicorns.find({ name: { $regex: /horn/ } })

// SQL: WHERE name LIKE '%a'
// MongoDB: names that end with "a"
db.unicorns.find({ name: { $regex: /a$/ } })

Case-insensitive search

By default, searches are case-sensitive. Use the i option to ignore case:

// Searches for "aurora" regardless of case
db.unicorns.find({ name: { $regex: /aurora/i } })

// You can also use string syntax
db.unicorns.find({ name: { $regex: "aurora", $options: "i" } })

Common patterns

// Starts with "A" or "B" (case-insensitive)
db.unicorns.find({ name: { $regex: /^[AB]/i } })

// Contains "horn" or "corn"
db.unicorns.find({ name: { $regex: /(horn|corn)/ } })

// Names that are exactly 5 letters
db.unicorns.find({ name: { $regex: /^.{5}$/ } })

Available options

  • i: case-insensitive (ignores case)
  • m: multiline (^ and $ consider each line)
  • s: dotall (the dot . includes line breaks)
  • x: verbose (allows spaces and comments in the expression)

Important: regex searches can be slow on large collections. For better performance, create an index on the field and use patterns that start with ^ (anchored to the beginning).

Sorting results

Use sort to sort:

// By weight descending
db.unicorns.find().sort({ weight: -1 })

// By gender ascending, then vampires descending
db.unicorns.find().sort({ gender: 1, vampires: -1 })
  • 1 = ascending order
  • -1 = descending order

Limiting results

Use limit to get only the first N results:

// The 3 heaviest unicorns
db.unicorns.find().sort({ weight: -1 }).limit(3)

Use skip to skip results:

// Skips the first 5 and returns the next 3
db.unicorns.find().skip(5).limit(3)

Counting documents

To count documents that match a filter:

db.unicorns.countDocuments({ vampires: { $gt: 50 } })

The $exists operator

To search for documents that have (or don't have) a field:

// Documents that have the 'vampires' field
db.unicorns.find({ vampires: { $exists: true } })

// Documents that do NOT have the 'vampires' field
db.unicorns.find({ vampires: { $exists: false } })
Activity 1

Use comparison operators and filters with the Airbnb data:

  1. Find listings that accommodate 4 or more people (accommodates)
  2. Find listings with a review score greater than 4.5 (review_scores_rating)
  3. Find listings in CIUTAT VELLA OR POBLATS MARITIMS (use $in)
  4. Sort all listings by number_of_reviews from highest to lowest and show the first 10
  5. Find listings that have between 10 and 50 reviews (use $gte and $lte)

Pro:

  1. Find listings that meet ALL of these conditions: CIUTAT VELLA neighborhood, type "Entire home/apt", more than 10 reviews and a score greater than 4.0
  2. Find listings where the host has more than 5 properties (host_total_listings_count)
  3. Find listings that are NOT in the EXTRAMURS neighborhood and that accommodate more than 6 people (use $ne and $gt)
  4. Find listings whose name contains the word "beach" or "playa" (use $regex with $options: "i" to ignore case)
  5. Find listings where the host name (host_name) starts with the letter "A" (use $regex with the pattern ^A)
  6. Find listings whose name contains "centro" OR "center" (use $regex with the pattern (centro|center) and the "i" option)

Solutions

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Desafíos de programación atemporales y multiparadigmáticos

Desafíos de programación atemporales y multiparadigmáticos

Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.

Buy the book

Will you buy me a coffee?

This is how I keep writing without ads or paywalls.

Comments

There are no comments yet.