Permalink
Browse files

Implement query language for test_find_advanced

  • Loading branch information...
1 parent 0ee1d8a commit d85b36392ec9be4f42e40fb4a61f9e8d677a5a31 @gdb committed Jul 10, 2011
Showing with 71 additions and 10 deletions.
  1. +43 −1 lib/embedded-mongo/backend/collection.rb
  2. +5 −5 lib/embedded-mongo/backend/manager.rb
  3. +23 −4 lib/embedded-mongo/util.rb
@@ -63,7 +63,49 @@ def insert(doc)
def selector_match?(selector, doc)
raise NotImplementedError.new('Does not current support $where queries') if selector.has_key?('$where')
- selector.all? { |k, v| doc[k] == v }
+ selector.all? { |k, v| partial_match?(v, doc[k]) }
+ end
+
+ def partial_match?(partial_selector, value)
+ EmbeddedMongo.log.debug("partial_match? #{partial_selector.inspect} #{value.inspect}")
+ case partial_selector
+ when Array, String, BSON::ObjectId, nil
+ partial_selector == value
+ when Hash
+ if partial_selector.all? { |k, v| !k.start_with?('$') }
+ partial_selector == value
+ else
+ raise NotImplementedError.new("Cannot mix $ directives with non: #{partial_selector.inspect}") if partial_selector.any? { |k, v| !k.start_with?('$') }
+ partial_selector.all? do |k, v|
+ directive_match?(k, v, value)
+ end
+ end
+ else
+ raise "Unsupported selector #{partial_selector.inspect}"
+ end
+ end
+
+ def directive_match?(directive_key, directive_value, value)
+ case directive_key
+ when '$lt'
+ raise NotImplementedError.new("Only implemented for numeric directive values: #{directive_value.inspect}") unless directive_value.kind_of?(Numeric)
+ value and value < directive_value
+ when '$gt'
+ raise NotImplementedError.new("Only implemented for numeric directive values: #{directive_value.inspect}") unless directive_value.kind_of?(Numeric)
+ value and value > directive_value
+ when '$gte'
+ raise NotImplementedError.new("Only implemented for numeric directive values: #{directive_value.inspect}") unless directive_value.kind_of?(Numeric)
+ value and value >= directive_value
+ when '$lte'
+ raise NotImplementedError.new("Only implemented for numeric directive values: #{directive_value.inspect}") unless directive_value.kind_of?(Numeric)
+ value and value <= directive_value
+ when '$in'
+ raise NotImplementedError.new("Only implemented for arrays: #{directive_value.inspect}") unless directive_value.kind_of?(Array)
+ directive_value.include?(value)
+ else
+ raise NotImplementedError.new("Have yet to implement: #{directive_key}")
+ # raise Mongo::OperationFailure.new("invalid operator: #{directive_key}")
+ end
end
def apply_update!(update, doc)
@@ -6,14 +6,14 @@ def initialize(spec)
end
def insert_documents(db_name, collection_name, documents)
- documents.each { |doc| EmbeddedMongo::Util.stringify_keys!(doc) }
+ documents.each { |doc| EmbeddedMongo::Util.stringify_hash!(doc) }
EmbeddedMongo.log.info("INSERT: #{db_name.inspect} #{collection_name.inspect} #{documents.inspect}")
collection = get_collection(db_name, collection_name)
collection.insert_documents(documents)
end
def find(db_name, collection_name, selector)
- EmbeddedMongo::Util.stringify_keys!(selector)
+ EmbeddedMongo::Util.stringify_hash!(selector)
EmbeddedMongo.log.info("FIND: #{db_name.inspect} #{collection_name.inspect} #{selector.inspect}")
if collection_name == '$cmd'
db = get_db(db_name)
@@ -24,15 +24,15 @@ def find(db_name, collection_name, selector)
end
def update(db_name, collection_name, selector, update, opts)
- EmbeddedMongo::Util.stringify_keys!(selector)
- EmbeddedMongo::Util.stringify_keys!(update)
+ EmbeddedMongo::Util.stringify_hash!(selector)
+ EmbeddedMongo::Util.stringify_hash!(update)
EmbeddedMongo.log.info("FIND: #{db_name.inspect} #{collection_name.inspect} #{selector.inspect} #{update.inspect} #{opts.inspect}")
collection = get_collection(db_name, collection_name)
collection.update(selector, update, opts)
end
def remove(db_name, collection_name, selector, opts)
- EmbeddedMongo::Util.stringify_keys!(selector)
+ EmbeddedMongo::Util.stringify_hash!(selector)
EmbeddedMongo.log.info("REMOVE: #{db_name.inspect} #{collection_name.inspect} #{selector.inspect} #{opts.inspect}")
collection = get_collection(db_name, collection_name)
collection.remove(selector, opts)
View
@@ -1,10 +1,29 @@
module EmbeddedMongo
module Util
- def self.stringify_keys!(hash)
- hash.keys.each do |key|
- hash[key.to_s] = hash.delete(key)
+ # TODO: make this recursive / stringify values
+ def self.stringify_hash!(hash)
+ raise ArgumentError.new("Argument is not a hash: #{hash.inspect}") unless hash.kind_of?(Hash)
+ stringify!(hash)
+ end
+
+ private
+
+ def self.stringify!(struct)
+ case struct
+ when Hash
+ struct.keys.each do |key|
+ struct[key.to_s] = stringify!(struct.delete(key))
+ end
+ struct
+ when Array
+ struct.each_with_index { |entry, i| struct[i] = stringify!(entry) }
+ when Symbol
+ struct.to_s
+ when String, Integer, BSON::ObjectId, nil
+ struct
+ else
+ raise "Cannot stringify #{struct.inspect}"
end
- hash
end
end
end

0 comments on commit d85b363

Please sign in to comment.