Запрос MongoDB с условием 'или' - PullRequest
58 голосов
/ 05 января 2010

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

Я хочу запросить текущих членов группы. «Текущий» означает, что время начала меньше текущего времени, а время истечения больше текущего времени ИЛИ ноль.

Этот условный запрос полностью блокирует меня. Я мог бы сделать это, выполнив два запроса и объединив результаты, но это кажется уродливым и требует загрузки всех результатов одновременно. Или я мог бы установить по умолчанию время истечения на какую-то произвольную дату в далеком будущем, но это кажется еще более уродливым и потенциально хрупким. В SQL я бы просто выразил это как «(expires> = Now ()) ИЛИ (expires IS NULL)» - но я не знаю, как это сделать в Mongo.

Есть идеи? Большое спасибо заранее.

Ответы [ 5 ]

91 голосов
/ 02 июля 2010

Просто подумал, что обновлю на тот случай, если кто-нибудь наткнется на эту страницу в будущем. Начиная с 1.5.3, mongo теперь поддерживает реальный оператор $ или: http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or

Ваш запрос "(expires> = Now ()) OR (expires IS NULL)" теперь может быть обработан как:

{$or: [{expires: {$gte: new Date()}}, {expires: null}]}
49 голосов
/ 13 декабря 2012

Если кто-нибудь найдет это полезным, www.querymongo.com выполняет перевод между SQL и MongoDB, включая операторы OR. Это может быть очень полезно для определения синтаксиса, когда вы знаете эквивалент SQL.

В случае операторов OR это выглядит следующим образом

SQL:

SELECT * FROM collection WHERE columnA = 3 OR columnB = 'string';

MongoDB:

db.collection.find({
    "$or": [{
        "columnA": 3
    }, {
        "columnB": "string"
    }]
});
5 голосов
/ 05 января 2010

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

Используйте «in» или «where».

Это будет примерно так:

db.mycollection.find( { $where : function() { 
return ( this.startTime < Now() && this.expireTime > Now() || this.expireTime == null ); } } );
2 голосов
/ 05 декабря 2018

db.Lead.find (

{"name": {'$regex' : '.*' + "Ravi" + '.*'}},
{
"$or": [{
    'added_by':"arunkrishna@aarux.com"
}, {
    'added_by':"aruna@aarux.com"
}]
}

);

2 голосов
/ 21 января 2010

Использование запроса $where будет медленным, отчасти потому, что он не может использовать индексы. Для такого рода проблем, я думаю, было бы лучше сохранить высокое значение для поля «expires», которое, естественно, всегда будет больше, чем Now (). Вы можете либо сохранить очень высокую дату в миллионах лет в будущем, либо использовать отдельный тип, чтобы указать никогда. Порядок сортировки по кросс-типу определен в здесь .

Хороший выбор - пустой Regex или MaxKey (если ваш язык поддерживает это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...