ddr-core 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +12 -0
- data/README.md +27 -0
- data/Rakefile +30 -0
- data/app/assets/config/ddr_core_manifest.js +0 -0
- data/app/controllers/users/omniauth_callbacks_controller.rb +11 -0
- data/app/controllers/users/sessions_controller.rb +15 -0
- data/app/models/concerns/ddr/captionable.rb +25 -0
- data/app/models/concerns/ddr/describable.rb +108 -0
- data/app/models/concerns/ddr/governable.rb +25 -0
- data/app/models/concerns/ddr/has_admin_metadata.rb +141 -0
- data/app/models/concerns/ddr/has_attachments.rb +10 -0
- data/app/models/concerns/ddr/has_children.rb +10 -0
- data/app/models/concerns/ddr/has_content.rb +132 -0
- data/app/models/concerns/ddr/has_extracted_text.rb +10 -0
- data/app/models/concerns/ddr/has_intermediate_file.rb +25 -0
- data/app/models/concerns/ddr/has_multires_image.rb +14 -0
- data/app/models/concerns/ddr/has_parent.rb +18 -0
- data/app/models/concerns/ddr/has_struct_metadata.rb +21 -0
- data/app/models/concerns/ddr/has_thumbnail.rb +33 -0
- data/app/models/concerns/ddr/solr_document_behavior.rb +429 -0
- data/app/models/concerns/ddr/streamable.rb +25 -0
- data/app/models/ddr/admin_set.rb +28 -0
- data/app/models/ddr/attachment.rb +14 -0
- data/app/models/ddr/collection.rb +28 -0
- data/app/models/ddr/component.rb +31 -0
- data/app/models/ddr/contact.rb +23 -0
- data/app/models/ddr/digest.rb +8 -0
- data/app/models/ddr/file.rb +40 -0
- data/app/models/ddr/item.rb +36 -0
- data/app/models/ddr/language.rb +31 -0
- data/app/models/ddr/media_type.rb +22 -0
- data/app/models/ddr/resource.rb +94 -0
- data/app/models/ddr/rights_statement.rb +25 -0
- data/app/models/ddr/target.rb +17 -0
- data/config/initializers/devise.rb +262 -0
- data/config/locales/ddr-core.en.yml +85 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20141104181418_create_users.rb +34 -0
- data/db/migrate/20141107124012_add_columns_to_user.rb +46 -0
- data/lib/ddr-core.rb +1 -0
- data/lib/ddr/auth.rb +80 -0
- data/lib/ddr/auth/ability.rb +18 -0
- data/lib/ddr/auth/ability_definitions.rb +26 -0
- data/lib/ddr/auth/ability_definitions/admin_set_ability_definitions.rb +9 -0
- data/lib/ddr/auth/ability_definitions/alias_ability_definitions.rb +23 -0
- data/lib/ddr/auth/ability_definitions/attachment_ability_definitions.rb +13 -0
- data/lib/ddr/auth/ability_definitions/collection_ability_definitions.rb +28 -0
- data/lib/ddr/auth/ability_definitions/component_ability_definitions.rb +13 -0
- data/lib/ddr/auth/ability_definitions/item_ability_definitions.rb +13 -0
- data/lib/ddr/auth/ability_definitions/lock_ability_definitions.rb +13 -0
- data/lib/ddr/auth/ability_definitions/publication_ability_definitions.rb +16 -0
- data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +39 -0
- data/lib/ddr/auth/ability_definitions/superuser_ability_definitions.rb +9 -0
- data/lib/ddr/auth/ability_factory.rb +10 -0
- data/lib/ddr/auth/abstract_ability.rb +48 -0
- data/lib/ddr/auth/affiliation.rb +14 -0
- data/lib/ddr/auth/affiliation_groups.rb +20 -0
- data/lib/ddr/auth/anonymous_ability.rb +7 -0
- data/lib/ddr/auth/auth_context.rb +109 -0
- data/lib/ddr/auth/auth_context_factory.rb +13 -0
- data/lib/ddr/auth/detached_auth_context.rb +19 -0
- data/lib/ddr/auth/dynamic_groups.rb +13 -0
- data/lib/ddr/auth/effective_permissions.rb +12 -0
- data/lib/ddr/auth/effective_roles.rb +9 -0
- data/lib/ddr/auth/failure_app.rb +16 -0
- data/lib/ddr/auth/group.rb +40 -0
- data/lib/ddr/auth/grouper_gateway.rb +70 -0
- data/lib/ddr/auth/groups.rb +32 -0
- data/lib/ddr/auth/ldap_gateway.rb +74 -0
- data/lib/ddr/auth/permissions.rb +18 -0
- data/lib/ddr/auth/remote_groups.rb +14 -0
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +56 -0
- data/lib/ddr/auth/roles.rb +28 -0
- data/lib/ddr/auth/roles/role.rb +121 -0
- data/lib/ddr/auth/roles/role_type.rb +23 -0
- data/lib/ddr/auth/roles/role_types.rb +52 -0
- data/lib/ddr/auth/superuser_ability.rb +7 -0
- data/lib/ddr/auth/test_helpers.rb +22 -0
- data/lib/ddr/auth/user.rb +54 -0
- data/lib/ddr/auth/web_auth_context.rb +29 -0
- data/lib/ddr/core.rb +110 -0
- data/lib/ddr/core/engine.rb +8 -0
- data/lib/ddr/core/version.rb +5 -0
- data/lib/ddr/error.rb +16 -0
- data/lib/ddr/files.rb +13 -0
- data/lib/ddr/fits.rb +189 -0
- data/lib/ddr/index.rb +29 -0
- data/lib/ddr/index/abstract_query_result.rb +22 -0
- data/lib/ddr/index/connection.rb +38 -0
- data/lib/ddr/index/csv_query_result.rb +84 -0
- data/lib/ddr/index/document_builder.rb +9 -0
- data/lib/ddr/index/field.rb +35 -0
- data/lib/ddr/index/field_attribute.rb +22 -0
- data/lib/ddr/index/fields.rb +154 -0
- data/lib/ddr/index/filter.rb +139 -0
- data/lib/ddr/index/query.rb +82 -0
- data/lib/ddr/index/query_builder.rb +185 -0
- data/lib/ddr/index/query_clause.rb +112 -0
- data/lib/ddr/index/query_params.rb +40 -0
- data/lib/ddr/index/query_result.rb +102 -0
- data/lib/ddr/index/response.rb +30 -0
- data/lib/ddr/index/sort_order.rb +28 -0
- data/lib/ddr/index/unique_key_field.rb +12 -0
- data/lib/ddr/managers.rb +9 -0
- data/lib/ddr/managers/manager.rb +13 -0
- data/lib/ddr/managers/technical_metadata_manager.rb +141 -0
- data/lib/ddr/structure.rb +188 -0
- data/lib/ddr/structures/agent.rb +49 -0
- data/lib/ddr/structures/component_type_term.rb +29 -0
- data/lib/ddr/structures/div.rb +64 -0
- data/lib/ddr/structures/f_locat.rb +54 -0
- data/lib/ddr/structures/file.rb +52 -0
- data/lib/ddr/structures/file_grp.rb +35 -0
- data/lib/ddr/structures/file_sec.rb +22 -0
- data/lib/ddr/structures/fptr.rb +31 -0
- data/lib/ddr/structures/mets_hdr.rb +37 -0
- data/lib/ddr/structures/mptr.rb +49 -0
- data/lib/ddr/structures/struct_map.rb +40 -0
- data/lib/ddr/utils.rb +185 -0
- data/lib/ddr/vocab.rb +22 -0
- data/lib/ddr/vocab/asset.rb +51 -0
- data/lib/ddr/vocab/contact.rb +9 -0
- data/lib/ddr/vocab/display.rb +9 -0
- data/lib/ddr/vocab/duke_terms.rb +13 -0
- data/lib/ddr/vocab/rdf_vocabulary_parser.rb +43 -0
- data/lib/ddr/vocab/roles.rb +25 -0
- data/lib/ddr/vocab/sources/duketerms.rdf +870 -0
- data/lib/ddr/vocab/vocabulary.rb +37 -0
- data/lib/ddr/workflow.rb +8 -0
- data/lib/tasks/ddr/core_tasks.rake +4 -0
- metadata +428 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require "virtus"
|
|
2
|
+
require "forwardable"
|
|
3
|
+
|
|
4
|
+
module Ddr::Index
|
|
5
|
+
class Query
|
|
6
|
+
include Virtus.model
|
|
7
|
+
extend Forwardable
|
|
8
|
+
extend Deprecation
|
|
9
|
+
|
|
10
|
+
attribute :q, String, default: '*:*'
|
|
11
|
+
attribute :fields, Array[FieldAttribute], default: [ ]
|
|
12
|
+
attribute :filters, Array[Filter], default: [ ]
|
|
13
|
+
attribute :sort, Array[String], default: [ ]
|
|
14
|
+
attribute :rows, Integer
|
|
15
|
+
|
|
16
|
+
delegate [:count, :docs, :ids, :each_id, :all] => :result
|
|
17
|
+
delegate :params => :query_params
|
|
18
|
+
|
|
19
|
+
def self.build(*args, &block)
|
|
20
|
+
new.tap do |query|
|
|
21
|
+
query.build(*args, &block)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize(**args, &block)
|
|
26
|
+
super(**args)
|
|
27
|
+
if block_given?
|
|
28
|
+
build(&block)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def inspect
|
|
33
|
+
"#<#{self.class.name} q=#{q.inspect}, filters=#{filters.inspect}," \
|
|
34
|
+
" sort=#{sort.inspect}, rows=#{rows.inspect}, fields=#{fields.inspect}>"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_s
|
|
38
|
+
URI.encode_www_form(params)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def pids
|
|
42
|
+
Deprecation.warn(QueryResult, "`pids` is deprecated; use `ids` instead.")
|
|
43
|
+
ids
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def each_pid(&block)
|
|
47
|
+
Deprecation.warn(QueryResult, "`each_pid` is deprecated; use `each_id` instead.")
|
|
48
|
+
each_id(&block)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def result
|
|
52
|
+
QueryResult.new(self)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def csv
|
|
56
|
+
CSVQueryResult.new(self)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def filter_clauses
|
|
60
|
+
filters.map(&:clauses).flatten
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def query_params
|
|
64
|
+
QueryParams.new(self)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def build(*args, &block)
|
|
68
|
+
QueryBuilder.new(self, *args, &block)
|
|
69
|
+
self
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def ==(other)
|
|
73
|
+
other.instance_of?(self.class) &&
|
|
74
|
+
other.q == self.q &&
|
|
75
|
+
other.fields == self.fields &&
|
|
76
|
+
other.filters == self.filters &&
|
|
77
|
+
other.rows == self.rows &&
|
|
78
|
+
other.sort == self.sort
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
module Ddr::Index
|
|
2
|
+
#
|
|
3
|
+
# QueryBuilder - Provides a DSL for building a Query.
|
|
4
|
+
#
|
|
5
|
+
# Note: Where a method receives a [field] parameter, the parameter value is
|
|
6
|
+
# coerced to a Field instance. See FieldAttribute#coerce for details.
|
|
7
|
+
#
|
|
8
|
+
# *** DSL METHODS ***
|
|
9
|
+
#
|
|
10
|
+
# absent [field]
|
|
11
|
+
# Adds a filter selecting documents where the field is not present (no values).
|
|
12
|
+
#
|
|
13
|
+
# asc [field], ...
|
|
14
|
+
# Adds ascending orderings by the fields specified.
|
|
15
|
+
#
|
|
16
|
+
# See also: desc, order_by
|
|
17
|
+
#
|
|
18
|
+
# before [field], [date_time]
|
|
19
|
+
# Adds a filter selecting documents where the field has a date/time before
|
|
20
|
+
# (earlier than) the value.
|
|
21
|
+
#
|
|
22
|
+
# before_days [field], [int]
|
|
23
|
+
# Adds a filter selecting documents where the field has a date/time the
|
|
24
|
+
# specified number of days before today (now) or earlier.
|
|
25
|
+
#
|
|
26
|
+
# desc [field], ...
|
|
27
|
+
# Adds descending orderings by the fields specified.
|
|
28
|
+
#
|
|
29
|
+
# See also: asc, order_by
|
|
30
|
+
#
|
|
31
|
+
# filter [filter1], ...
|
|
32
|
+
# Adds filters to the query.
|
|
33
|
+
#
|
|
34
|
+
# Aliased as: filters
|
|
35
|
+
#
|
|
36
|
+
# filters [filter], ...
|
|
37
|
+
# Alias for: filter
|
|
38
|
+
#
|
|
39
|
+
# field [field1], ...
|
|
40
|
+
# Adds fields to result documents.
|
|
41
|
+
# Note that all fields are returned when none is specified.
|
|
42
|
+
#
|
|
43
|
+
# Aliased as: fields
|
|
44
|
+
#
|
|
45
|
+
# fields [field], ...
|
|
46
|
+
# Alias for: field
|
|
47
|
+
#
|
|
48
|
+
# id [doc_id]
|
|
49
|
+
# For selecting a single document by ID.
|
|
50
|
+
#
|
|
51
|
+
# join [from: {field1}, to: {field2}, where: {condition}]
|
|
52
|
+
# Adds a Solr join clause (see https://wiki.apache.org/solr/Join)
|
|
53
|
+
#
|
|
54
|
+
# limit [int]
|
|
55
|
+
# Limits the number of documents returned by the query.
|
|
56
|
+
#
|
|
57
|
+
# Aliased as: rows
|
|
58
|
+
#
|
|
59
|
+
# model [model_name], ...
|
|
60
|
+
# Adds a filter selecting document where ActiveFedora model equals value
|
|
61
|
+
# or one of the values.
|
|
62
|
+
#
|
|
63
|
+
# negative [field], [value]
|
|
64
|
+
# Adds a filter selecting document where field does not have the value.
|
|
65
|
+
#
|
|
66
|
+
# order_by [{field => order, ...}], ...
|
|
67
|
+
# Adds ordering(s) to the query.
|
|
68
|
+
#
|
|
69
|
+
# Aliased as: sort
|
|
70
|
+
#
|
|
71
|
+
# present [field]
|
|
72
|
+
# Adds a filter selecting document where the field has any value.
|
|
73
|
+
#
|
|
74
|
+
# q [query_clause]
|
|
75
|
+
# Sets a query clause for the `q` parameter.
|
|
76
|
+
#
|
|
77
|
+
# raw [clause1], ...
|
|
78
|
+
# Adds a filter of "raw" query clauses (i.e., pre-constructed).
|
|
79
|
+
#
|
|
80
|
+
# regexp [field], [regexp]
|
|
81
|
+
# Adds a filter selecting documents where the field has a value
|
|
82
|
+
# matching the regular expression.
|
|
83
|
+
# Slashes (/) in the regexp will be escaped as required by Solr.
|
|
84
|
+
#
|
|
85
|
+
# rows [int]
|
|
86
|
+
# Alias for: limit
|
|
87
|
+
#
|
|
88
|
+
# sort [{field => order, ...}]
|
|
89
|
+
# Alias for: order_by
|
|
90
|
+
#
|
|
91
|
+
# term [{field => value, ...}]
|
|
92
|
+
# Adds a filter of "term" query clauses for the fields and values.
|
|
93
|
+
#
|
|
94
|
+
# where [{field => value, ...}]
|
|
95
|
+
# Adds a filter of "standard" query clauses.
|
|
96
|
+
# Values will be escaped when the filter is serialized.
|
|
97
|
+
# If a hash value is an array, that query clause will select documents
|
|
98
|
+
# where the field matches any array entry.
|
|
99
|
+
#
|
|
100
|
+
class QueryBuilder
|
|
101
|
+
|
|
102
|
+
attr_reader :query
|
|
103
|
+
|
|
104
|
+
def initialize(*args, &block)
|
|
105
|
+
@query = args.first.is_a?(Query) ? args.shift : Query.new
|
|
106
|
+
if block_given?
|
|
107
|
+
instance_exec(*args, &block)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param pid [String]
|
|
112
|
+
# @return [QueryBuilder]
|
|
113
|
+
def id(pid)
|
|
114
|
+
q QueryClause.id(pid)
|
|
115
|
+
limit 1
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @param filters [Array<Filter>]
|
|
119
|
+
# @return [QueryBuilder]
|
|
120
|
+
def filter(*filters)
|
|
121
|
+
query.filters += filters
|
|
122
|
+
self
|
|
123
|
+
end
|
|
124
|
+
alias_method :filters, :filter
|
|
125
|
+
|
|
126
|
+
# @param fields [Array<Field>]
|
|
127
|
+
# @return [QueryBuilder] self
|
|
128
|
+
def field(*fields)
|
|
129
|
+
query.fields += fields.flatten.map { |f| FieldAttribute.coerce(f) }
|
|
130
|
+
self
|
|
131
|
+
end
|
|
132
|
+
alias_method :fields, :field
|
|
133
|
+
|
|
134
|
+
# @param num [Integer]
|
|
135
|
+
# @return [QueryBuilder] self
|
|
136
|
+
def limit(num)
|
|
137
|
+
query.rows = num.to_i
|
|
138
|
+
self
|
|
139
|
+
end
|
|
140
|
+
alias_method :rows, :limit
|
|
141
|
+
|
|
142
|
+
# @param orderings [Hash<Field, String>]
|
|
143
|
+
# @return [QueryBuilder] self
|
|
144
|
+
def order_by(*orderings)
|
|
145
|
+
query.sort += orderings.first.map { |field, order| SortOrder.new(field: field, order: order) }
|
|
146
|
+
self
|
|
147
|
+
end
|
|
148
|
+
alias_method :sort, :order_by
|
|
149
|
+
|
|
150
|
+
# @param fields [Array<Field, Symbol, String>]
|
|
151
|
+
# @return [QueryBuilder] self
|
|
152
|
+
def asc(*fields)
|
|
153
|
+
query.sort += fields.map { |field| SortOrder.asc(field) }
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
# @param fields [Array<Field, Symbol, String>]
|
|
157
|
+
# @return [QueryBuilder] self
|
|
158
|
+
def desc(*fields)
|
|
159
|
+
query.sort += fields.map { |field| SortOrder.desc(field) }
|
|
160
|
+
self
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# @param query_clause [QueryClause, String]
|
|
164
|
+
# @return [QueryBuilder] self
|
|
165
|
+
def q(query_clause)
|
|
166
|
+
query.q = query_clause
|
|
167
|
+
self
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
|
|
172
|
+
def respond_to_missing?(name, include_all)
|
|
173
|
+
Filter::ClassMethods.public_instance_methods.include?(name)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def method_missing(name, *args, &block)
|
|
177
|
+
if respond_to?(name)
|
|
178
|
+
filter Filter.send(name, *args)
|
|
179
|
+
else
|
|
180
|
+
super
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require "virtus"
|
|
2
|
+
|
|
3
|
+
module Ddr::Index
|
|
4
|
+
class QueryClause
|
|
5
|
+
include Virtus.value_object
|
|
6
|
+
|
|
7
|
+
ANY_FIELD = Field.new('*').freeze
|
|
8
|
+
ANY_VALUE = "[* TO *]"
|
|
9
|
+
QUOTE = '"'
|
|
10
|
+
|
|
11
|
+
TERM_QUERY = "{!term f=%{field}}%{value}"
|
|
12
|
+
STANDARD_QUERY = "%{field}:%{value}"
|
|
13
|
+
NEGATIVE_QUERY = "-%{field}:%{value}"
|
|
14
|
+
DISJUNCTION = "{!lucene q.op=OR df=%{field}}%{value}"
|
|
15
|
+
REGEXP_QUERY = "%{field}:/%{value}/"
|
|
16
|
+
|
|
17
|
+
values do
|
|
18
|
+
attribute :field, FieldAttribute
|
|
19
|
+
attribute :value, String
|
|
20
|
+
attribute :quote_value, Boolean, default: false
|
|
21
|
+
attribute :template, String, default: STANDARD_QUERY
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_s
|
|
25
|
+
template % { field: field, value: quote_value ? quote(value) : value }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def quote(value)
|
|
29
|
+
self.class.quote(value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
def quote(value)
|
|
34
|
+
# Derived from Blacklight::Solr::SearchBuilderBehavior#solr_param_quote
|
|
35
|
+
unless value =~ /\A[a-zA-Z0-9$_\-\^]+\z/
|
|
36
|
+
QUOTE + value.gsub("'", "\\\\\'").gsub('"', "\\\\\"") + QUOTE
|
|
37
|
+
else
|
|
38
|
+
value
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Builds a query clause to retrieve the index document by unique key.
|
|
43
|
+
def unique_key(value)
|
|
44
|
+
term(UniqueKeyField.instance, value)
|
|
45
|
+
end
|
|
46
|
+
alias_method :id, :unique_key
|
|
47
|
+
|
|
48
|
+
def where(field, value)
|
|
49
|
+
values = Array(value)
|
|
50
|
+
if values.size > 1
|
|
51
|
+
disjunction(field, values)
|
|
52
|
+
else
|
|
53
|
+
new(field: field, value: values.first, quote_value: true)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Builds a query clause to filter where field does not have the given value.
|
|
58
|
+
def negative(field, value)
|
|
59
|
+
new(field: field, value: value, template: NEGATIVE_QUERY, quote_value: true)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Builds a query clause to filter where field is present (i.e, has any value)
|
|
63
|
+
def present(field)
|
|
64
|
+
new(field: field, value: ANY_VALUE)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Builds a query clause to filter where field is NOT present (no values)
|
|
68
|
+
def absent(field)
|
|
69
|
+
new(field: field, value: ANY_VALUE, template: NEGATIVE_QUERY)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Builds a query clause to filter where field contains at least one of a set of values.
|
|
73
|
+
def disjunction(field, values)
|
|
74
|
+
value = values.map { |v| quote(v) }.join(" ")
|
|
75
|
+
new(field: field, value: value, template: DISJUNCTION)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Builds a Solr join clause
|
|
79
|
+
# @see https://wiki.apache.org/solr/Join
|
|
80
|
+
def join(from:, to:, where:)
|
|
81
|
+
field, value = where.to_a.first
|
|
82
|
+
from_field = FieldAttribute.coerce(from)
|
|
83
|
+
to_field = FieldAttribute.coerce(to)
|
|
84
|
+
template = "{!join from=#{from_field} to=#{to_field}}%{field}:%{value}"
|
|
85
|
+
new(field: field, value: value, template: template, quote_value: true)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Builds a query clause to filter where date field value is earlier than a date/time value.
|
|
89
|
+
def before(field, value)
|
|
90
|
+
new(field: field, value: "[* TO %s]" % Ddr::Utils.solr_date(value))
|
|
91
|
+
end
|
|
92
|
+
alias_method :before_date_time, :before
|
|
93
|
+
|
|
94
|
+
# Builds a query clause to filter where date field value is earlier than a number of days before now.
|
|
95
|
+
def before_days(field, value)
|
|
96
|
+
new(field: field, value: "[* TO NOW-%iDAYS]" % value)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Builds a "term query" clause to filter where field contains value.
|
|
100
|
+
def term(field, value)
|
|
101
|
+
new(field: field, value: value, template: TERM_QUERY)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Builds a regular expression query clause
|
|
105
|
+
def regexp(field, value)
|
|
106
|
+
val = value.gsub(/\//, "\\/")
|
|
107
|
+
new(field: field, value: val, template: REGEXP_QUERY)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Ddr::Index
|
|
2
|
+
class QueryParams
|
|
3
|
+
|
|
4
|
+
attr_reader :query
|
|
5
|
+
|
|
6
|
+
def initialize(query)
|
|
7
|
+
@query = query
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def params
|
|
11
|
+
{ q: q_param,
|
|
12
|
+
fq: filter_queries,
|
|
13
|
+
fl: fields,
|
|
14
|
+
sort: sort,
|
|
15
|
+
rows: rows,
|
|
16
|
+
}.select { |k, v| v.present? }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def q_param
|
|
20
|
+
query.q.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def filter_queries
|
|
24
|
+
query.filter_clauses.map(&:to_s)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fields
|
|
28
|
+
query.fields.join(",")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def sort
|
|
32
|
+
query.sort.join(",")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def rows
|
|
36
|
+
query.rows
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Ddr::Index
|
|
2
|
+
class QueryResult < AbstractQueryResult
|
|
3
|
+
extend Deprecation
|
|
4
|
+
|
|
5
|
+
PAGE_SIZE = 1000
|
|
6
|
+
|
|
7
|
+
delegate :csv, to: :query
|
|
8
|
+
|
|
9
|
+
def each(&block)
|
|
10
|
+
if params[:rows]
|
|
11
|
+
each_unpaginated(&block)
|
|
12
|
+
else
|
|
13
|
+
each_paginated(&block)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def each_unpaginated(&block)
|
|
18
|
+
Connection.select(params).docs.each(&block)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def each_paginated(&block)
|
|
22
|
+
pages.each { |pg| pg.each(&block) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def pids
|
|
26
|
+
Deprecation.warn(QueryResult,
|
|
27
|
+
"`pids` is deprecated; use `ids` instead." \
|
|
28
|
+
" (called from #{caller.first})"
|
|
29
|
+
)
|
|
30
|
+
ids
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def ids
|
|
34
|
+
Enumerator.new do |e|
|
|
35
|
+
each do |doc|
|
|
36
|
+
e << doc[Fields::ID]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def each_pid(&block)
|
|
42
|
+
Deprecation.warn(QueryResult,
|
|
43
|
+
"`each_pid` is deprecated; use `each_id` instead." \
|
|
44
|
+
" (called from #{caller.first})"
|
|
45
|
+
)
|
|
46
|
+
each_id(&block)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def each_id(&block)
|
|
50
|
+
ids.each(&block)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def docs
|
|
54
|
+
Enumerator.new do |e|
|
|
55
|
+
each do |doc|
|
|
56
|
+
e << DocumentBuilder.build(doc)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def objects
|
|
62
|
+
Enumerator.new do |e|
|
|
63
|
+
each_id do |id|
|
|
64
|
+
e << ActiveFedora::Base.find(id)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def facet_fields
|
|
70
|
+
response = Connection.select(params, rows: 0)
|
|
71
|
+
response.facet_fields.each_with_object({}) do |(field, values), memo|
|
|
72
|
+
memo[field] = Hash[*values]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def all
|
|
77
|
+
to_a
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def pages
|
|
81
|
+
num = 1
|
|
82
|
+
Enumerator.new do |e|
|
|
83
|
+
loop do
|
|
84
|
+
pg = page(num)
|
|
85
|
+
e << pg
|
|
86
|
+
unless pg.has_next?
|
|
87
|
+
break
|
|
88
|
+
end
|
|
89
|
+
num += 1
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def page(num)
|
|
95
|
+
page_params = params.dup
|
|
96
|
+
page_size = page_params.delete(:rows) || PAGE_SIZE
|
|
97
|
+
response = Connection.page(num, page_size, "select", params: page_params)
|
|
98
|
+
response.docs
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|