В прошлом уроке мы искали документ по номеру. Но покупатель приходит в магазин не с номером книги, а с вопросом: «есть что-нибудь из фантастики до 500 рублей?». Сегодня учимся задавать такие вопросы. Все примеры на учебной базе магазина.
Запрос по образцу
Представь, что ты ищешь в шкафу папку и описываешь её помощнику: «синяя, на корешке написано 2025». Ты не объясняешь, как искать, ты описываешь, что найти. Помощник сам переберёт полки.
Запрос в MongoDB устроен так же. Ты передаёшь в find документ-образец, фильтр, и база возвращает все документы, которые под него подходят:
db.books.findOne({ title: 'Шинель' })
{
_id: 5,
title: 'Шинель',
genre: 'повесть',
price: 250,
pages: 64,
year: 1842,
author: { _id: 3, name: 'Гоголь', country: 'Россия' },
tags: [ 'классика' ]
}
Методов чтения два:
findOneвозвращает первый подходящий документ илиnull;findвозвращает все подходящие документы.
Документы бывают длинными, поэтому дальше в find будет второй аргумент: какие поля показать. Например, { title: 1, _id: 0 } значит «только название, без _id». Подробно о нём в следующем уроке, а пока читай его как «покажи название».
db.books.find({ genre: 'фантастика' }, { title: 1, _id: 0 })
[ { title: 'Пикник на обочине' }, { title: 'Трудно быть богом' } ]
Поле с конкретным значением в фильтре означает «равно». Если ничего не нашлось, mongosh промолчит: пустой результат он не печатает.
Операторы сравнения
«Равно» мало. Чтобы спросить «больше» или «меньше», вместо значения пишут документ с оператором. Операторы начинаются со знака доллара:
| Оператор | Значит | Аналог в SQL |
|---|---|---|
$eq | равно | = |
$ne | не равно | <> |
$gt, $gte | больше, больше или равно | >, >= |
$lt, $lte | меньше, меньше или равно | <, <= |
$in, $nin | входит в список, не входит | IN, NOT IN |
Книги дороже 600 рублей и книги от 400 до 600:
db.books.find({ price: { $gt: 600 } }, { title: 1, price: 1, _id: 0 })
db.books.find({ price: { $gte: 400, $lte: 600 } }, { title: 1, price: 1, _id: 0 })
[
{ title: 'Мастер и Маргарита', price: 690 },
{ title: 'Мёртвые души', price: 610 },
{ title: 'Грокаем алгоритмы', price: 1290 },
{ title: 'Совершенный код', price: 2490 }
]
[
{ title: 'Пикник на обочине', price: 450 },
{ title: 'Трудно быть богом', price: 520 }
]
Два оператора на одном поле в одном документе работают как «и»: так получается диапазон. Список значений задаёт $in:
db.books.find({ genre: { $in: ['повесть', 'учебник'] } }, { title: 1, genre: 1, _id: 0 })
[
{ title: 'Собачье сердце', genre: 'повесть' },
{ title: 'Шинель', genre: 'повесть' },
{ title: 'Грокаем алгоритмы', genre: 'учебник' },
{ title: 'Совершенный код', genre: 'учебник' },
{ title: 'Нос', genre: 'повесть' }
]
Тип значения важен. В базе цены это числа, поэтому { price: { $gt: '500' } } со строкой '500' не найдёт ни одной книги: MongoDB сравнивает значения одного типа и не превращает строку в число.
И, или
Несколько полей в фильтре соединяются через «и». Романы, написанные до 1900 года:
db.books.find({ genre: 'роман', year: { $lt: 1900 } }, { title: 1, _id: 0 })
[ { title: 'Мёртвые души' } ]
Для «или» есть оператор $or. Он принимает массив условий, и документ подходит, если выполнено хотя бы одно. Учебники или совсем короткие книги:
db.books.find(
{ $or: [{ genre: 'учебник' }, { pages: { $lt: 100 } }] },
{ title: 1, _id: 0 }
)
[
{ title: 'Шинель' },
{ title: 'Грокаем алгоритмы' },
{ title: 'Совершенный код' },
{ title: 'Нос' }
]
Есть и явный $and с таким же массивом. Он нужен редко: когда два условия на одно и то же поле нельзя уложить в один документ, например два $or.
урок из курса
Урок из курса «MongoDB с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.