Перейти к содержанию

Критерии запроса

Запросы могут выходить за рамки точного соответствия, описанного в предыдущем разделе; они могут соответствовать более сложным критериям, таким как диапазоны, операторы OR и отрицание.

Условные операторы

"$lt", "$lte", "$gt" и "$gte" – все это операторы сравнения, соответствующие <, <=, > и >= соответственно. Их можно комбинировать для поиска диапазона значений. Например, чтобы найти пользователей в возрасте от 18 до 30 лет, можно выполнить следующий запрос:

1
> db.users.find({"age": {"$gte": 18, "$lte": 30}})

При этом будут найдены все документы, где поле age было больше или равно 18 и меньше или равно 30.

Эти типы запросов диапазона часто полезны, когда речь идет о датах. Например, чтобы найти людей, которые зарегистрировались до 1 января 2007 года, можно выполнить следующий запрос:

1
2
> start = new Date("01/01/2007")
> db.users.find({"registered" : {"$lt" : start}})

В зависимости от того, как вы создаете и храните даты, точное совпадение может быть менее полезным, поскольку даты хранятся с точностью до миллисекунды. Часто вам требуется целый день, неделя или месяц, что делает необходимым запрос по диапазону.

Чтобы запросить документы, в которых значение ключа не равно определенному значению, нужно использовать другой условный оператор $ne, который означает «не равно». Если вы хотите найти всех пользователей, у которых нет имени «joe», можно запросить их таким образом:

1
> db.users.find({"username" : {"$ne" : "joe"}})

Оператор $ne можно использовать с любым типом.

Запросы с оператором OR

В MongoDB есть два способа выполнить запрос оператором OR. Оператор $in может использоваться для запроса различных значений для одного ключа. Оператор $or является более общим; его можно использовать для запроса любого из заданных значений по нескольким ключам.

Если у вас имеется более одного возможного значения для одного ключа, используйте массив критериев с $in. Например, предположим, что мы проводим розыгрыш и номера выигрышных билетов – 75, 542 и 390. Чтобы найти все три этих документа, можно создать следующий запрос:

1
> db.raffle.find({"ticket_no": {"$in": [725, 542, 390]}})

Оператор $in очень гибкий и позволяет указывать критерии различных типов, а также значения. Например, если мы постепенно переносим нашу схему, чтобы использовать имена пользователей вместо идентификаторов пользователей, можно запросить любой из них:

1
> db.users.find({"user_id": {"$in": [12345, "joe"]}})

Этот запрос сопоставляет документы, где user_id равен 12 345, и документы, где user_id имеет значение joe.

Если оператору $in задан массив с одним значением, он ведет себя так же, как и прямое сопоставление со значением. Например, {ticket_no: {$in: [725]}} совпадает с теми же документами, что и {ticket_no: 725}.

Противоположностью оператору $in является оператор $nin, который возвращает документы, которые не соответствуют ни одному из критериев в массиве. Если мы хотим вернуть всех тех, кто ничего не выиграл во время лотереи, это можно сделать с помощью следующего запроса:

1
> db.raffle.find({"ticket_no": {"$ nin": [725, 542, 390]}})

Этот запрос возвращает всех, у кого не было билетов с этими номерами. Оператор $in дает вам запрос OR для одного ключа, но что, если нам нужно найти документы, где ticket_no равен 725 или значение winner равно true? Для этого типа запроса нам понадобится использовать условный оператор $or. $or принимает массив возможных критериев. В случае с лотереей использование оператора $or будет выглядеть так:

1
> db.raffle.find({"$or": [{"ticket_no": 725}, {"winner": true}]})

$or может содержать другие условия. Если, например, мы хотим сопоставить любое из трех значений ticket_no или ключ winner, можно использовать это:

1
2
3
4
> db.raffle.find(
    {"$or" : [{"ticket_no" : {"$in" : [725, 542, 390]}},
    {"winner" : true}]}
)

С помощью обычного запроса типа AND вы хотите максимально сузить результаты, используя как можно меньше аргументов. Запросы типа OR действуют наоборот: они наиболее эффективны, если первые аргументы соответствуют как можно большему количеству документов.

Хотя оператор $or будет работать, всегда, когда это возможно, используйте $in, поскольку оптимизатор запросов обрабатывает его более эффективно.

$not

$not является метаусловным оператором: его можно применять поверх любых других критериев. В качестве примера давайте рассмотрим оператор модуля $mod. $mod запрашивает ключи, значения которых при делении на первое заданное значение имеют остаток от второго значения:

1
> db.users.find({"id_num": {"$mod": [5, 1]}})

Предыдущий запрос возвращает пользователей с номерами 1, 6, 11, 16 и т. д. Если вместо этого мы хотим вернуть пользователей с номерами 2, 3, 4, 5, 7, 8, 9, 10, 12 и т. д., можно использовать оператор $not:

1
> db.users.find({"id_num": {"$not": {"$mod": [5, 1]}}})

$not может быть особенно полезен в сочетании с регулярными выражениями для поиска всех документов, которые не соответствуют заданному шаблону (использование регулярных выражений описано в разделе «Регулярные выражения»).

Комментарии