Reputation: 571
I have a field in my mongo database with a hash value, example:
Company.find('testCompany').categories
=> {"architects"=>"architects", "landscape_designers"=>"landscape_designers"}
How can i do a .where select on this field? So i can find entries by single categories? Like i search my database for "landscape_designers" and get all entries who have it included in there categories hash
I found something like
Company.where(:'categories.landscape_designers'.gt => 0)
but it is not working.
thanks in advance!
Upvotes: 1
Views: 1451
Reputation: 434665
If the key and value in the categories
Hash are always the same then:
Company.where('categories.landscape_designers' => 'landscape_designers')
should do the trick. If you just want to see if there's a landscape_designers
key in categories
then you could use $exists
:
Company.where(:'categories.landscape_designers'.exists => true)
Company.where('categories.landscape_designers' => { :$exists => true })
Note that:
$exists
does match documents that contain the field that stores thenull
value.
so $exists
will match :categories => { :landscape_designers => nil }
. If you want to exclude that pathological case then:
Company.where(:'categories.landscape_designers'.ne => nil)
Company.where('categories.landscape_designers' => { :$ne => nil })
In any case, I think you a design problem with your schema. Your categories
appear to be a set rather than a Hash so you're confusing the fields logical type with its implementation. You could use an Array instead of a Hash and let MongoDB's multi-keys take care of searching the array; for example, your model would say:
field :categories, :type => Array
# and maybe some uniqueness validation or cleanup
and then you could treat the array as a scalar in your searches:
Company.where(:categories => 'landscape_designers')
Then MongoDB will unwrap the array for you.
You could also monkey patch a couple things into Set
:
class Set
def mongoize
self.to_a
end
def self.demongoize(object)
self.new(object)
end
def self.mongoize(object)
if(object.is_a?(Set))
object.mongoize
else
object
end
end
def self.evolve(object)
if(object.is_a?(Set))
object.mongoize
else
object
end
end
end
and then use:
field :categories, :type => Set
to get automatic set behavior in Ruby-land and an Array inside MongoDB.
Upvotes: 3
Reputation: 793
Use this in your Company model
def method_name
categories.where("landscape_designers > ?", 0)
end
Upvotes: -1