lib/mongo_adapter/query.rb in dm-mongo-adapter-0.2.0.pre3 vs lib/mongo_adapter/query.rb in dm-mongo-adapter-0.6.0
- old
+ new
@@ -1,11 +1,11 @@
module DataMapper
module Mongo
# This class is responsible for taking Query instances from DataMapper and
# formatting the query such that it can be performed by the Mongo library.
class Query
- include Extlib::Assertions
+ include DataMapper::Assertions
include DataMapper::Query::Conditions
# Creates a new Query instance
#
# @param [Mongo::Collection] collection
@@ -40,11 +40,11 @@
def count
setup_conditions_and_options
# TODO: atm ruby driver doesn't support count with statements,
# that's why we use find and size here as a tmp workaround
- if @statements.blank?
+ if @statements.keys.empty?
[@collection.count]
else
[find.size]
end
end
@@ -66,11 +66,11 @@
keys << field.name
property_names << field.name
end
end
- if operators.blank?
+ if operators.empty?
initial = {}
reduce = JavaScript::Reduce.new.to_s
finalize = nil
else
js_operation = JavaScript::Operation.new(operators)
@@ -79,26 +79,31 @@
reduce = js_operation.reduce
finalize = js_operation.finalize
keys = keys - initial.keys
end
-
- @collection.group(keys, @statements, initial, reduce, true, finalize).map do |records|
- records.to_mash.symbolize_keys.only(*property_names)
+
+ opts = {
+ :key => keys, :cond => @statements, :initial => initial,
+ :reduce => reduce, :finalize => finalize
+ }
+
+ @collection.group(opts).map do |records|
+ DataMapper::Ext::Hash.to_mash(records).symbolize_keys
end
end
private
# TODO: document
# @api private
def setup_conditions_and_options
@options = {}
-
+
@options[:limit] = @query.limit if @query.limit
@options[:skip] = @query.offset if @query.offset
- @options[:sort] = sort_statement(@query.order) unless @query.order.empty?
+ @options[:sort] = sort_statement(@query.order) unless @query.order.nil?
conditions_statement(@query.conditions)
end
# TODO: document
@@ -142,20 +147,10 @@
when AndOperation then operation.each{|op| conditions_statement(op, affirmative)}
when OrOperation then operation.each{|op| conditions_statement(op, affirmative)}
end
end
- # TODO: document
- # @api private
- def comparison_statement_for_embedment(comparison, affirmative = true)
- embedment = @query.model.embedments.values.detect { |e| e.target_model == comparison.subject.model }
-
- field = "#{embedment.storage_name}.#{comparison.subject.field}"
-
- update_statements(comparison, field, affirmative)
- end
-
# Takes a Comparison condition and returns a Mongo-compatible hash
#
# @param [DataMapper::Query::Conditions::Comparison] comparison
# An comparison to be made suitable for use with Mongo
# @param [Boolean] affirmative
@@ -168,43 +163,45 @@
def comparison_statement(comparison, affirmative = true)
if comparison.relationship?
return conditions_statement(comparison.foreign_key_mapping, affirmative)
end
- if comparison.subject.model && comparison.subject.model < EmbeddedResource
- return comparison_statement_for_embedment(comparison, affirmative)
- end
-
update_statements(comparison, comparison.subject.field, affirmative)
end
# TODO: document
# @api private
- def update_statements(comparison, field, affirmative = true)
- value = comparison.value
+ def
+ update_statements(comparison, field, affirmative = true)
+ value = if comparison.value.kind_of?(Array)
+ comparison.value.map { |value| value.class.to_mongo(value) }
+ else
+ comparison.value.class.to_mongo(comparison.value)
+ end
operator = if affirmative
- case comparison
- when EqualToComparison then value
- when GreaterThanComparison then {'$gt' => value}
- when LessThanComparison then {'$lt' => value}
- when GreaterThanOrEqualToComparison then {'$gte' => value}
- when LessThanOrEqualToComparison then {'$lte' => value}
- when InclusionComparison then inclusion_comparison_operator(comparison, value)
- when RegexpComparison then value
- when LikeComparison then comparison.send(:expected)
- else
- raise NotImplementedError
- end
- else
- case comparison
- when EqualToComparison then {'$ne' => value}
- when InclusionComparison then {'$nin' => value}
- else
- raise NotImplementedError
- end
- end
+ case comparison
+ when EqualToComparison then value
+ when GreaterThanComparison then {'$gt' => value}
+ when LessThanComparison then {'$lt' => value}
+ when GreaterThanOrEqualToComparison then {'$gte' => value}
+ when LessThanOrEqualToComparison then {'$lte' => value}
+ when InclusionComparison then inclusion_comparison_operator(comparison, value)
+ when RegexpComparison then value
+ when LikeComparison then comparison.send(:expected)
+ else
+ raise NotImplementedError
+ end
+ else
+ case comparison
+ when EqualToComparison then {'$ne' => value}
+ when InclusionComparison then {'$nin' => value}
+ when RegexpComparison then {'$not' => value}
+ else
+ raise NotImplementedError
+ end
+ end
operator.is_a?(Hash) ?
(@statements[field.to_sym] ||= {}).merge!(operator) : @statements[field.to_sym] = operator
end
@@ -221,10 +218,10 @@
def inclusion_comparison_operator(comparison, value)
if value.kind_of?(Range)
{'$gte' => value.first, value.exclude_end? ? '$lt' : '$lte' => value.last}
elsif comparison.kind_of?(InclusionComparison) && value.size == 1
value.first
- elsif comparison.subject.type == DataMapper::Mongo::Types::EmbeddedArray
+ elsif comparison.subject.kind_of?(DataMapper::Mongo::Property::Array)
value
else
{'$in' => value}
end
end