Как я могу получить отрицание mongoid запроса? - PullRequest
1 голос
/ 27 января 2012

В моем приложении у меня есть запрос:

Model.where(flagged: true, saved: false)

В качестве альтернативы я могу использовать Model.all(:conditions => {flagged: true, saved: false})

Всё хорошо.

Теперь, как мне получить отрицание этого запроса? т.е. все экземпляры модели, которые не удовлетворяют flagged: true И saved: false (что эквивалентно flagged != true ИЛИ saved != false)

Model.excludes(flagged: true, saved: false) возвращает мне экземпляры, которые удовлетворяют flagged != true И saved != false)

Ответы [ 4 ]

1 голос
/ 28 января 2012

Чтобы сделать это, вам нужно открыть драйвер Ruby MongoDB.

Если я правильно понимаю вопрос, команда Mongoid exclude делает AND, когда вы ищете OR между предложениями $ ne, и для него нет метода.

Вот что вам нужно в оболочке:

find({$or: [{flagged: {$ne: true}}, {saved: {$ne: true}}]})

В ruby ​​этот запрос выглядит так:

query = {"$or" => [{"flagged" => {"$ne" => true}}, {"saved" => {"$ne" => true}}]}

Если я правильно помню, вы можете сказать:

Model.collection.find(query) где запрос - это документ, который я определил выше, и он должен работать.

0 голосов
/ 21 марта 2014

Вы пробовали $nor оператор?

Model.all(:conditions => { '$nor' => [ { flagged: true }, { saved: false } ]})

Подробнее: http://docs.mongodb.org/manual/reference/operator/query/nor/

0 голосов
/ 27 января 2012

Я обнаружил, что могу сделать это, используя Синтаксис выражения Javascript

Итак, отрицание Model.where(flagged: true, saved: false) - которое можно выразить как Model.where("this.flagged == true && this.saved == false")

это

Model.where("!(this.flagged == true && this.saved == false)")

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

Если кто-то может дать ответ, который использует только собственный язык запросов, без выполнения явного расширения булевой логики, я отмечу это как правильное (возможно, это будет возможно в будущей версии Mongodb / Mongoid - если сможет) не будет сделано сейчас.)

0 голосов
/ 27 января 2012

Для конкретного случая, который вы используете в своем вопросе, вы можете сделать:

Model.any_of({ flagged: false, saved: true }, { flagged: true, saved: true }, { flagged: false, saved: false } )

Однако, как вы говорите в своих комментариях, вы на самом деле ищете общее решение. AFAIK, нет никакого способа сделать это в Mongoid или в MongoDB.

Причина этого, скорее всего, заключается в том, что вы не можете делать соединения в запросе MongoDB. Например, традиционным способом SQL для получения отрицания запроса может быть:

SELECT * FROM mytable t 
WHERE t.id NOT IN ( SELECT t2.id FROM mytable t2 WHERE t2.condition = true )

Или, чтобы избежать проблемы выбора N + 1

SELECT t.*, t2.id FROM mytable t
OUTER JOIN mytable t2 ON ( t1.id AND t2.condition = true )
WHERE t2.id = NULL

Обе они основаны на том, чтобы каким-то образом объединить два выбора, чего в Монго вы не можете сделать.

Единственный другой способ - это как-то инвертировать логику, как я, чтобы получить ответ выше на ваш конкретный пример. Я думаю, что было бы очень плохой идеей попросить Mongo сделать это автоматически, поскольку в результате вы получите код, генерирующий произвольно сложные запросы, которые вы не сможете контролировать и не сможете оптимизировать.

...