Подтвердить что ты не робот

Запрос MongoDB с условием "или"

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

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

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

Любые идеи? Большое спасибо заранее.

4b9b3361

Ответ 1

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

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

{$or: [{expires: {$gte: new Date()}}, {expires: null}]}

Ответ 2

В случае, если кто-либо найдет это полезным, 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"
    }]
});

Ответ 3

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

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

Это будет что-то вроде этого:

db.mycollection.find( { $where : function() { 
return ( this.startTime < Now() && this.expireTime > Now() || this.expireTime == null ); } } );

Ответ 4

Использование запроса $where будет медленным, отчасти потому, что он не может использовать индексы. Для такого рода проблем я думаю, что было бы лучше сохранить высокое значение для поля "expires", которое, естественно, всегда будет больше, чем Now(). Вы можете либо хранить очень высокую дату в миллионы лет в будущем, либо использовать тип "seporate", чтобы никогда не указывать. Порядок сортировки кросс-типа определяется http://www.mongodb.org/display/DOCS/Compare+Order+for+Types. Пустое Regex или MaxKey (если вы его поддерживаете) являются хорошим выбором.