MongoMapper is a great MongoDB ORM for Ruby on Rails. It basically allows you to use MongoDB as a drop-in replacement for MySQL/PostgreSQL.
However, it has one particular weakness: It is impossible to filter MongoDB queries by exact array values. MongoMapper converts array queries into $in operations, which means that all documents that contain any of the specified array values will be returned.
For example, assume you have two MongoDB documents:
{ "name": "A", "items": [1, 2, 3] }
{ "name": "B", "items": [1, 2] }
The following MongoMapper query will return both documents, even if you might have expected only the first one:
MyModel.where(:items => [1, 2, 3])
My $exact fork on GitHub
I've created a fork of plucky, the query engine used by MongoMapper, which adds a new pseudo operator called $exact. My fork can be found here:
kennu/plucky (master, based on v0.4.1) kennu/plucky/tree/backport_exact_v3 (backported to v0.3.8)
I've also submitted my change set as a pull request to the author of plucky.
You can use the fork in your Rails Gemfile like this (you'll need the v0.3.8 version with current mongo_mapper):
gem 'plucky', :git => 'https://github.com/kennu/plucky.git', :branch => 'backport_exact_v3'
gem 'mongo_mapper'
After running bundle install, you can specify queries in the this format:
MyModel.where(:items => { :$exact => [1, 2, 3] })
This query will return only the first document of the previous example above.
Remember, though, that you must keep your arrays in a specific order for these queries to work. An array of [1, 2, 3] won't match if you query it as [2, 3, 1].