Ildar
Ildar

Reputation: 343

Mongoid: multiple checks on a single field

I need to select transactions with the same type as a given transaction. And I need to check that it doesn't return all transactions with the nil type.

With ActiveRecord I can easily write:

given_transaction = Transaction.first
needed_transactions = Transaction.where('type != nil and type = ?', given_transaction.type)

and all works

when I try to write the same thing with mongoid:

needed_transactions = Transaction.where(:type => given_transaction.type, :type.ne => nil)

It generates the following query:

"query"=>{:type=>{"$ne"=>"planned"}}

In other words, mongoid ignores the first check and only uses the last check on the field.

I tried "all_of", "all_in", "and" — and still can't find the working solution.

Maybe I am doing something wrong... My world is going upside down because of this... :(((

Upvotes: 2

Views: 1372

Answers (1)

mu is too short
mu is too short

Reputation: 434665

From the fine manual:

All queries in Mongoid are Criteria, which is a chainable and lazily evaluated wrapper to a MongoDB dynamic query.

And looking at the Criteria docs for where we see a bunch of examples with a single condition. But remember the chainability mentioned above. Perhaps you're looking for this:

needed_transactions = Transaction.where(:type => given_transaction.type).where(:type.ne => nil)

The Criteria#and docs might make good reading as well:

Adds another simple expression that must match in order to return results. This is the same as Criteria#where and is mostly here for syntactic sugar.

MONGOID
# Match all people with last name Jordan and first name starting with d.
Person.where(last_name: "Jordan").and(first_name: /^d/i)

MONGODB QUERY SELECTOR
{ "last_name" : "Jordan", "first_name" : /^d/i }

I have to admit that I don't understand why you're checking :type twice like that though; if given_transaction.type.nil? is possible then you could deal with that without even querying your database.

And BTW, with ActiveRecord you'd want to say this:

Transaction.where('type is not null and type = ?', given_transaction.type)

As far as the strange query you're getting is concerned, when you do this:

Transaction.where(:type => given_transaction.type, :type.ne => nil)

Mongoid ends up trying to build a Hash with two values for the :type key:

{ :type => 'planned' }
{ :type => { :$ne => nil } }

and somehow it ends up replacing the nil with 'planned'. I don't know the internal details of Mongoid's where or the methods it patches into Symbol, I'm just backtracking from the observed behavior.

Upvotes: 6

Related Questions