lib/ddr/index/query_builder.rb in ddr-models-3.0.0.beta.3 vs lib/ddr/index/query_builder.rb in ddr-models-3.0.0.beta.4

- old
+ new

@@ -1,74 +1,194 @@ module Ddr::Index + # + # QueryBuilder - Provides a DSL for building a Query. + # + # Note: Where a method receives a [field] parameter, the parameter value is + # coerced to a Field instance. See FieldAttribute#coerce for details. + # + # *** DSL METHODS *** + # + # absent [field] + # Adds a filter selecting documents where the field is not present (no values). + # + # asc [field], ... + # Adds ascending orderings by the fields specified. + # + # See also: desc, order_by + # + # before [field], [date_time] + # Adds a filter selecting documents where the field has a date/time before + # (earlier than) the value. + # + # before_days [field], [int] + # Adds a filter selecting documents where the field has a date/time the + # specified number of days before today (now) or earlier. + # + # desc [field], ... + # Adds descending orderings by the fields specified. + # + # See also: asc, order_by + # + # id [doc_id] + # For selecting a single document by ID. + # + # filter [filter1], ... + # Adds filters to the query. + # + # Aliased as: filters + # + # filters [filter], ... + # Alias for: filter + # + # field [field1], ... + # Adds fields to result documents. + # Note that all fields are returned when none is specified. + # + # Aliased as: fields + # + # fields [field], ... + # Alias for: field + # + # limit [int] + # Limits the number of documents returned by the query. + # + # Aliased as: rows + # + # model [model_name], ... + # Adds a filter selecting document where ActiveFedora model equals value + # or one of the values. + # + # negative [field], [value] + # Adds a filter selecting document where field does not have the value. + # + # order_by [{field => order, ...}], ... + # Adds ordering(s) to the query. + # + # Aliased as: sort + # + # present [field] + # Adds a filter selecting document where the field has any value. + # + # q [query_clause] + # Sets a query clause for the `q` parameter. + # + # raw [clause1], ... + # Adds a filter of "raw" query clauses (i.e., pre-constructed). + # + # rows [int] + # Alias for: limit + # + # sort [{field => order, ...}] + # Alias for: order_by + # + # term [{field => value, ...}] + # Adds a filter of "term" query clauses for the fields and values. + # + # where [{field => value, ...}] + # Adds a filter of "standard" query clauses. + # Values will be escaped when the filter is serialized. + # If a hash value is an array, that query clause will select documents + # where the field matches any array entry. + # class QueryBuilder + # Builds a Query object + # @yield [builder] a new QueryBuilder instance. + # @return [Query] def self.build + Deprecation.warn(self, + "`Ddr::Index::QueryBuilder.build` is deprecated and will be removed in ddr-models 3.0." \ + " Use `Ddr::Index::QueryBuilder.new` instead.") builder = new yield builder builder.query end - def initialize - @q = nil - @fields = [ ] - @filters = [ ] - @sort = [ ] - @rows = nil - end + attr_reader :query - def query - Query.new.tap do |qry| - instance_variables.each do |var| - qry.instance_variable_set(var, instance_variable_get(var)) - end + def initialize(query = nil, &block) + @query = query || Query.new + if block_given? + instance_eval &block end end + # @param pid [String] + # @return [QueryBuilder] def id(pid) q QueryClause.id(pid) limit 1 end - def filter(*fltrs) - @filters.push *fltrs + # @param filters [Array<Filter>] + # @return [QueryBuilder] + def filter(*filters) + query.filters += filters self end + alias_method :filters, :filter - def fields(*flds) - @fields.push *flds + # @param fields [Array<Field>] + # @return [QueryBuilder] self + def field(*fields) + query.fields += fields.flatten.map { |f| FieldAttribute.coerce(f) } self end + alias_method :fields, :field + # @param num [Integer] + # @return [QueryBuilder] self def limit(num) - @rows = num + query.rows = num.to_i self end + alias_method :rows, :limit - def order_by(field, order) - @sort << [field, order].join(" ") + # @param orderings [Hash<Field, String>] + # @return [QueryBuilder] self + def order_by(*orderings) + unless orderings.first.is_a? Hash + Deprecation.warn(QueryBuilder, "`order_by` will require a hash of orderings in ddr-models 3.0.") + field, order = orderings + return order_by(field => order) + end + query.sort += orderings.first.map { |field, order| SortOrder.new(field: field, order: order) } self end + alias_method :sort, :order_by - def asc(field) - order_by field, "asc" + # @param fields [Array<Field, Symbol, String>] + # @return [QueryBuilder] self + def asc(*fields) + query.sort += fields.map { |field| SortOrder.asc(field) } + self end - - def desc(field) - order_by field, "desc" + # @param fields [Array<Field, Symbol, String>] + # @return [QueryBuilder] self + def desc(*fields) + query.sort += fields.map { |field| SortOrder.desc(field) } + self end - def q(q) - @q = q + # @param query_clause [QueryClause, String] + # @return [QueryBuilder] self + def q(query_clause) + query.q = query_clause self end - protected + private + def respond_to_missing?(name, include_all) + Filter::ClassMethods.public_instance_methods.include?(name) + end + def method_missing(name, *args, &block) - if Filter.respond_to? name - return filter Filter.send(name, *args, &block) + if respond_to?(name) + filter Filter.send(name, *args) + else + super end - super end end end