ddr-models 2.0.1 → 2.1.0.rc1
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 +4 -4
- data/README.md +23 -17
- data/app/models/collection.rb +1 -35
- data/ddr-models.gemspec +2 -1
- data/lib/ddr/actions.rb +1 -0
- data/lib/ddr/actions/virus_check.rb +28 -0
- data/lib/ddr/auth.rb +4 -0
- data/lib/ddr/auth/ability_definitions/datastream_ability_definitions.rb +7 -5
- data/lib/ddr/auth/grouper_gateway.rb +9 -1
- data/lib/ddr/auth/permissions.rb +2 -1
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +5 -5
- data/lib/ddr/auth/roles/role_types.rb +2 -1
- data/lib/ddr/datastreams.rb +2 -2
- data/lib/ddr/datastreams/administrative_metadata_datastream.rb +27 -14
- data/lib/ddr/datastreams/datastream_behavior.rb +13 -0
- data/lib/ddr/datastreams/fits_datastream.rb +88 -0
- data/lib/ddr/derivatives/png_generator.rb +2 -0
- data/lib/ddr/derivatives/ptif_generator.rb +2 -0
- data/lib/ddr/events/fixity_check_event.rb +2 -2
- data/lib/ddr/events/virus_check_event.rb +2 -14
- data/lib/ddr/index.rb +29 -0
- data/lib/ddr/index/abstract_query_result.rb +23 -0
- data/lib/ddr/index/connection.rb +17 -0
- data/lib/ddr/index/csv_query_result.rb +61 -0
- data/lib/ddr/index/document_builder.rb +9 -0
- data/lib/ddr/index/field.rb +23 -0
- data/lib/ddr/index/fields.rb +83 -0
- data/lib/ddr/index/filter.rb +48 -0
- data/lib/ddr/index/filters.rb +19 -0
- data/lib/ddr/index/legacy_license_fields.rb +14 -0
- data/lib/ddr/index/query.rb +35 -0
- data/lib/ddr/index/query_builder.rb +74 -0
- data/lib/ddr/index/query_clause.rb +52 -0
- data/lib/ddr/index/query_result.rb +70 -0
- data/lib/ddr/index/query_value.rb +16 -0
- data/lib/ddr/index/response.rb +13 -0
- data/lib/ddr/index/unique_key_field.rb +12 -0
- data/lib/ddr/index_fields.rb +7 -53
- data/lib/ddr/jobs.rb +1 -1
- data/lib/ddr/jobs/fits_file_characterization.rb +51 -0
- data/lib/ddr/managers.rb +1 -0
- data/lib/ddr/managers/technical_metadata_manager.rb +104 -0
- data/lib/ddr/models.rb +39 -23
- data/lib/ddr/models/base.rb +0 -2
- data/lib/ddr/models/describable.rb +1 -1
- data/lib/ddr/models/effective_license.rb +9 -0
- data/lib/ddr/models/engine.rb +13 -0
- data/lib/ddr/models/file_management.rb +157 -160
- data/lib/ddr/models/governable.rb +0 -4
- data/lib/ddr/models/has_admin_metadata.rb +80 -72
- data/lib/ddr/models/has_children.rb +1 -1
- data/lib/ddr/models/has_content.rb +18 -0
- data/lib/ddr/models/has_struct_metadata.rb +5 -1
- data/lib/ddr/models/indexing.rb +32 -20
- data/lib/ddr/models/inherited_license.rb +13 -0
- data/lib/ddr/models/license.rb +38 -0
- data/lib/ddr/models/solr_document.rb +195 -211
- data/lib/ddr/models/version.rb +1 -1
- data/lib/ddr/models/year_facet.rb +154 -0
- data/lib/ddr/utils.rb +13 -1
- data/lib/ddr/vocab/roles.rb +0 -10
- data/spec/controllers/including_role_based_access_controls_enforcement_spec.rb +4 -4
- data/spec/datastreams/fits_datastream_spec.rb +84 -0
- data/spec/fixtures/fits/document.xml +65 -0
- data/spec/fixtures/fits/image.xml +59 -0
- data/spec/index/filter_spec.rb +47 -0
- data/spec/index/filters_spec.rb +17 -0
- data/spec/index/query_spec.rb +19 -0
- data/spec/jobs/fits_file_characterization_spec.rb +52 -0
- data/spec/managers/technical_metadata_manager_spec.rb +140 -0
- data/spec/models/active_fedora_datastream_spec.rb +44 -0
- data/spec/models/collection_spec.rb +7 -12
- data/spec/models/component_spec.rb +3 -6
- data/spec/models/effective_license_spec.rb +49 -0
- data/spec/models/has_admin_metadata_spec.rb +143 -194
- data/spec/models/has_struct_metadata_spec.rb +2 -2
- data/spec/models/indexing_spec.rb +40 -0
- data/spec/models/solr_document_spec.rb +96 -37
- data/spec/models/year_facet_spec.rb +65 -0
- data/spec/spec_helper.rb +1 -7
- data/spec/support/shared_examples_for_ddr_models.rb +0 -2
- data/spec/support/shared_examples_for_has_content.rb +37 -3
- metadata +79 -32
- data/lib/ddr/datastreams/properties_datastream.rb +0 -25
- data/lib/ddr/jobs/migrate_legacy_authorization.rb +0 -23
- data/lib/ddr/models/has_properties.rb +0 -15
- data/lib/ddr/models/licensable.rb +0 -28
- data/spec/auth/legacy_authorization_spec.rb +0 -94
- data/spec/auth/legacy_roles_spec.rb +0 -32
- data/spec/jobs/migrate_legacy_authorization_spec.rb +0 -43
- data/spec/support/shared_examples_for_has_properties.rb +0 -5
- data/spec/support/shared_examples_for_licensable.rb +0 -15
@@ -28,8 +28,8 @@ module Ddr
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def to_solr
|
31
|
-
{ Ddr::
|
32
|
-
Ddr::
|
31
|
+
{ Ddr::Index::Fields::LAST_FIXITY_CHECK_ON => event_date_time_s,
|
32
|
+
Ddr::Index::Fields::LAST_FIXITY_CHECK_OUTCOME => outcome }
|
33
33
|
end
|
34
34
|
|
35
35
|
protected
|
@@ -9,20 +9,8 @@ module Ddr
|
|
9
9
|
self.description = "Content file scanned for viruses"
|
10
10
|
|
11
11
|
def to_solr
|
12
|
-
{ Ddr::
|
13
|
-
Ddr::
|
14
|
-
end
|
15
|
-
|
16
|
-
# Message sent by ActiveSupport::Notifications
|
17
|
-
def self.call(*args)
|
18
|
-
notification = ActiveSupport::Notifications::Event.new(*args)
|
19
|
-
result = notification.payload[:result] # Ddr::Antivirus::ScanResult instance
|
20
|
-
create(pid: notification.payload[:pid],
|
21
|
-
event_date_time: result.scanned_at,
|
22
|
-
outcome: result.ok? ? SUCCESS : FAILURE,
|
23
|
-
software: result.version,
|
24
|
-
detail: result.to_s
|
25
|
-
)
|
12
|
+
{ Ddr::Index::Fields::LAST_VIRUS_CHECK_ON => event_date_time_s,
|
13
|
+
Ddr::Index::Fields::LAST_VIRUS_CHECK_OUTCOME => outcome }
|
26
14
|
end
|
27
15
|
|
28
16
|
end
|
data/lib/ddr/index.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Index
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
|
5
|
+
autoload :AbstractQueryResult
|
6
|
+
autoload :Connection
|
7
|
+
autoload :CSVQueryResult
|
8
|
+
autoload :DocumentBuilder
|
9
|
+
autoload :Field
|
10
|
+
autoload :Fields
|
11
|
+
autoload :Filter
|
12
|
+
autoload :Filters
|
13
|
+
autoload :LegacyLicenseFields
|
14
|
+
autoload :Query
|
15
|
+
autoload :QueryBuilder
|
16
|
+
autoload :QueryClause
|
17
|
+
autoload :QueryResult
|
18
|
+
autoload :QueryValue
|
19
|
+
autoload :Response
|
20
|
+
autoload :UniqueKeyField
|
21
|
+
|
22
|
+
def self.pids
|
23
|
+
builder = QueryBuilder.new
|
24
|
+
query = builder.query
|
25
|
+
query.pids
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class AbstractQueryResult
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :query, :conn
|
6
|
+
delegate :params, to: :query
|
7
|
+
|
8
|
+
def initialize(query)
|
9
|
+
@query = query
|
10
|
+
@conn = Connection.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def count
|
14
|
+
response = conn.select(params, rows: 0)
|
15
|
+
response.num_found
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
raise NotImplementedError, "Subclasses must implement `#each`."
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class Connection < SimpleDelegator
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
super RSolr.connect(ActiveFedora.solr_config)
|
6
|
+
end
|
7
|
+
|
8
|
+
def select(params, extra={})
|
9
|
+
Response.new get("select", params: params.merge(extra))
|
10
|
+
end
|
11
|
+
|
12
|
+
def page(*args)
|
13
|
+
Response.new paginate(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
module Ddr::Index
|
4
|
+
class CSVQueryResult < AbstractQueryResult
|
5
|
+
|
6
|
+
MAX_ROWS = 10**8
|
7
|
+
|
8
|
+
COL_SEP = CSV::DEFAULT_OPTIONS[:col_sep].freeze
|
9
|
+
QUOTE_CHAR = CSV::DEFAULT_OPTIONS[:quote_char].freeze
|
10
|
+
|
11
|
+
SOLR_CSV_OPTS = {
|
12
|
+
"csv.header" => "false",
|
13
|
+
"csv.mv.separator" => "|",
|
14
|
+
"wt" => "csv",
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
CSV_OPTS = {
|
18
|
+
return_headers: true,
|
19
|
+
write_headers: true,
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
attr_reader :csv_opts, :solr_csv_opts
|
23
|
+
|
24
|
+
def initialize(query, **opts)
|
25
|
+
super(query)
|
26
|
+
|
27
|
+
@solr_csv_opts = SOLR_CSV_OPTS.dup
|
28
|
+
@solr_csv_opts[:rows] ||= MAX_ROWS
|
29
|
+
|
30
|
+
@csv_opts = CSV_OPTS.dup
|
31
|
+
@csv_opts[:headers] = query.fields.map(&:label)
|
32
|
+
|
33
|
+
# Set column separator and quote character consistently
|
34
|
+
@csv_opts[:col_sep] = @solr_csv_opts["csv.separator"] = opts.fetch(:col_sep, COL_SEP)
|
35
|
+
@csv_opts[:quote_char] = @solr_csv_opts["csv.encapsulator"] = opts.fetch(:quote_char, QUOTE_CHAR)
|
36
|
+
end
|
37
|
+
|
38
|
+
def csv
|
39
|
+
CSV.new(data, csv_opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
def each
|
43
|
+
csv.each
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
csv.string
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def csv_params
|
53
|
+
params.merge(solr_csv_opts)
|
54
|
+
end
|
55
|
+
|
56
|
+
def data
|
57
|
+
conn.get "select", params: csv_params
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class Field < SimpleDelegator
|
3
|
+
|
4
|
+
attr_reader :base
|
5
|
+
|
6
|
+
def initialize(base, *args)
|
7
|
+
@base = base.to_s
|
8
|
+
name = if args.empty?
|
9
|
+
@base
|
10
|
+
elsif args.last.is_a?(Hash) && args.last[:solr_name]
|
11
|
+
args.last[:solr_name]
|
12
|
+
else
|
13
|
+
Solrizer.solr_name(base, *args)
|
14
|
+
end
|
15
|
+
super(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def label
|
19
|
+
I18n.t "ddr.index.fields.#{base}", default: base.titleize
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
module Fields
|
3
|
+
|
4
|
+
include LegacyLicenseFields
|
5
|
+
|
6
|
+
def self.get(name)
|
7
|
+
const_get(name.to_s.upcase, false)
|
8
|
+
end
|
9
|
+
|
10
|
+
ID = UniqueKeyField.instance
|
11
|
+
PID = UniqueKeyField.instance
|
12
|
+
|
13
|
+
ACCESS_ROLE = Field.new :access_role, :stored_sortable
|
14
|
+
ACTIVE_FEDORA_MODEL = Field.new :active_fedora_model, :stored_sortable
|
15
|
+
ADMIN_SET = Field.new :admin_set, :stored_sortable
|
16
|
+
ADMIN_SET_FACET = Field.new :admin_set_facet, :facetable
|
17
|
+
BOX_NUMBER_FACET = Field.new :box_number_facet, :facetable
|
18
|
+
COLLECTION_FACET = Field.new :collection_facet, :facetable
|
19
|
+
COLLECTION_URI = Field.new :collection_uri, :symbol
|
20
|
+
CONTENT_CONTROL_GROUP = Field.new :content_control_group, :searchable, type: :string
|
21
|
+
CONTENT_SIZE = Field.new :content_size, :stored_sortable, type: :integer
|
22
|
+
CONTENT_SIZE_HUMAN = Field.new :content_size_human, :symbol
|
23
|
+
CREATOR_FACET = Field.new :creator_facet, :facetable
|
24
|
+
DATE_FACET = Field.new :date_facet, :facetable
|
25
|
+
DATE_SORT = Field.new :date_sort, :sortable
|
26
|
+
DEPOSITOR = Field.new :depositor, :stored_sortable
|
27
|
+
DISPLAY_FORMAT = Field.new :display_format, :stored_sortable
|
28
|
+
DOI = Field.new :doi, :symbol
|
29
|
+
EXTRACTED_TEXT = Field.new :extracted_text, :searchable, type: :text
|
30
|
+
HAS_MODEL = Field.new :has_model, :symbol
|
31
|
+
IDENTIFIER_ALL = Field.new :identifier_all, :symbol
|
32
|
+
INTERNAL_URI = Field.new :internal_uri, :stored_sortable
|
33
|
+
IS_ATTACHED_TO = Field.new :is_attached_to, :symbol
|
34
|
+
IS_EXTERNAL_TARGET_FOR = Field.new :is_external_target_for, :symbol
|
35
|
+
IS_GOVERNED_BY = Field.new :is_governed_by, :symbol
|
36
|
+
IS_MEMBER_OF = Field.new :is_member_of, :symbol
|
37
|
+
IS_MEMBER_OF_COLLECTION = Field.new :is_member_of_collection, :symbol
|
38
|
+
IS_PART_OF = Field.new :is_part_of, :symbol
|
39
|
+
LAST_FIXITY_CHECK_ON = Field.new :last_fixity_check_on, :stored_sortable, type: :date
|
40
|
+
LAST_FIXITY_CHECK_OUTCOME = Field.new :last_fixity_check_outcome, :symbol
|
41
|
+
LAST_VIRUS_CHECK_ON = Field.new :last_virus_check_on, :stored_sortable, type: :date
|
42
|
+
LAST_VIRUS_CHECK_OUTCOME = Field.new :last_virus_check_outcome, :symbol
|
43
|
+
LICENSE = Field.new :license, :stored_sortable
|
44
|
+
LOCAL_ID = Field.new :local_id, :stored_sortable
|
45
|
+
MEDIA_SUB_TYPE = Field.new :content_media_sub_type, :facetable
|
46
|
+
MEDIA_MAJOR_TYPE = Field.new :content_media_major_type, :facetable
|
47
|
+
MEDIA_TYPE = Field.new :content_media_type, :symbol
|
48
|
+
MULTIRES_IMAGE_FILE_PATH = Field.new :multires_image_file_path, :stored_sortable
|
49
|
+
OBJECT_PROFILE = Field.new :object_profile, :displayable
|
50
|
+
OBJECT_STATE = Field.new :object_state, :stored_sortable
|
51
|
+
OBJECT_CREATE_DATE = Field.new :system_create, :stored_sortable, type: :date
|
52
|
+
OBJECT_MODIFIED_DATE = Field.new :system_modified, :stored_sortable, type: :date
|
53
|
+
PERMANENT_ID = Field.new :permanent_id, :stored_sortable, type: :string
|
54
|
+
PERMANENT_URL = Field.new :permanent_url, :stored_sortable, type: :string
|
55
|
+
POLICY_ROLE = Field.new :policy_role, :symbol
|
56
|
+
PUBLISHER_FACET = Field.new :publisher_facet, :facetable
|
57
|
+
RESEARCH_HELP_CONTACT = Field.new :research_help_contact, :stored_sortable
|
58
|
+
RESOURCE_ROLE = Field.new :resource_role, :symbol
|
59
|
+
SERIES_FACET = Field.new :series_facet, :facetable
|
60
|
+
SPATIAL_FACET = Field.new :spatial_facet, :facetable
|
61
|
+
STRUCT_MAPS = Field.new :struct_maps, :stored_sortable
|
62
|
+
TECHMD_COLOR_SPACE = Field.new :techmd_color_space, :symbol
|
63
|
+
TECHMD_CREATING_APPLICATION = Field.new :techmd_creating_application, :symbol
|
64
|
+
TECHMD_CREATION_TIME = Field.new :techmd_creation_time, :stored_searchable, type: :date
|
65
|
+
TECHMD_FILE_SIZE = Field.new :techmd_file_size, :stored_searchable, type: :integer
|
66
|
+
TECHMD_FITS_VERSION = Field.new :techmd_fits_version, :stored_sortable
|
67
|
+
TECHMD_FITS_DATETIME = Field.new :techmd_fits_datetime, :stored_sortable, type: :date
|
68
|
+
TECHMD_FORMAT_LABEL = Field.new :techmd_format_label, :symbol
|
69
|
+
TECHMD_FORMAT_VERSION = Field.new :techmd_format_version, :symbol
|
70
|
+
TECHMD_IMAGE_HEIGHT = Field.new :techmd_image_height, :stored_searchable, type: :integer
|
71
|
+
TECHMD_IMAGE_WIDTH = Field.new :techmd_image_width, :stored_searchable, type: :integer
|
72
|
+
TECHMD_MEDIA_TYPE = Field.new :techmd_media_type, :symbol
|
73
|
+
TECHMD_MODIFICATION_TIME = Field.new :techmd_modification_time, :stored_searchable, type: :date
|
74
|
+
TECHMD_PRONOM_IDENTIFIER = Field.new :techmd_pronom_identifier, :symbol
|
75
|
+
TECHMD_VALID = Field.new :techmd_valid, :symbol
|
76
|
+
TECHMD_WELL_FORMED = Field.new :techmd_well_formed, :symbol
|
77
|
+
TITLE = Field.new :title, :stored_sortable
|
78
|
+
TYPE_FACET = Field.new :type_facet, :facetable
|
79
|
+
WORKFLOW_STATE = Field.new :workflow_state, :stored_sortable
|
80
|
+
YEAR_FACET = Field.new :year_facet, solr_name: "year_facet_iim"
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class Filter
|
3
|
+
|
4
|
+
class << self
|
5
|
+
delegate :where, :raw, :before_days, :before, :present, :absent, to: :new
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :clauses
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@clauses = [ ]
|
12
|
+
end
|
13
|
+
|
14
|
+
def where(conditions)
|
15
|
+
clauses = conditions.map do |field, value|
|
16
|
+
if value.respond_to?(:each)
|
17
|
+
QueryClause.or_values(field, *value)
|
18
|
+
else
|
19
|
+
QueryClause.term(field, value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
raw *clauses
|
23
|
+
end
|
24
|
+
|
25
|
+
# Adds clause (String) w/o escaping
|
26
|
+
def raw(*clauses)
|
27
|
+
self.clauses += clauses
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def present(field)
|
32
|
+
raw QueryClause.present(field)
|
33
|
+
end
|
34
|
+
|
35
|
+
def absent(field)
|
36
|
+
raw QueryClause.absent(field)
|
37
|
+
end
|
38
|
+
|
39
|
+
def before(field, date_time)
|
40
|
+
raw QueryClause.before(field, date_time)
|
41
|
+
end
|
42
|
+
|
43
|
+
def before_days(field, days)
|
44
|
+
raw QueryClause.before_days(field, days)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
module Filters
|
3
|
+
|
4
|
+
HAS_CONTENT = Filter.where(Fields::ACTIVE_FEDORA_MODEL => ["Component", "Attachment", "Target"])
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def is_governed_by(pid)
|
8
|
+
Filter.where(Fields::IS_GOVERNED_BY => internal_uri(pid))
|
9
|
+
end
|
10
|
+
|
11
|
+
def internal_uri(pid)
|
12
|
+
ActiveFedora::Base.internal_uri(pid)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private_class_method :internal_uri
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
module LegacyLicenseFields
|
3
|
+
|
4
|
+
warn "[DEPRECATION] `Ddr::Index::LegacyLicenseFields` is deprecated and will be removed from ddr-models 3.0."
|
5
|
+
|
6
|
+
DEFAULT_LICENSE_DESCRIPTION = Field.new :default_license_description, type: :string
|
7
|
+
DEFAULT_LICENSE_TITLE = Field.new :default_license_title, type: :string
|
8
|
+
DEFAULT_LICENSE_URL = Field.new :default_license_url, type: :string
|
9
|
+
LICENSE_DESCRIPTION = Field.new :license_description, type: :string
|
10
|
+
LICENSE_TITLE = Field.new :license_title, type: :string
|
11
|
+
LICENSE_URL = Field.new :license_url, type: :string
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class Query
|
3
|
+
|
4
|
+
attr_reader :q, :fields, :filters, :sort, :rows
|
5
|
+
|
6
|
+
delegate :count, :docs, :pids, :each_pid, :all, to: :result
|
7
|
+
|
8
|
+
def inspect
|
9
|
+
"#<#{self.class.name} q=#{q.inspect}, filters=#{filters.inspect}," \
|
10
|
+
" sort=#{sort.inspect}, rows=#{rows.inspect}, fields=#{fields.inspect}>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
URI.encode_www_form(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def params
|
18
|
+
{ q: q,
|
19
|
+
fq: filters.map(&:clauses).flatten,
|
20
|
+
fl: fields.join(","),
|
21
|
+
sort: sort.join(","),
|
22
|
+
rows: rows,
|
23
|
+
}.select { |k, v| v.present? }
|
24
|
+
end
|
25
|
+
|
26
|
+
def result
|
27
|
+
QueryResult.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def csv(**opts)
|
31
|
+
CSVQueryResult.new(self, **opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
class QueryBuilder
|
3
|
+
|
4
|
+
def self.build
|
5
|
+
builder = new
|
6
|
+
yield builder
|
7
|
+
builder.query
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@q = nil
|
12
|
+
@fields = [ ]
|
13
|
+
@filters = [ ]
|
14
|
+
@sort = [ ]
|
15
|
+
@rows = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def query
|
19
|
+
Query.new.tap do |qry|
|
20
|
+
instance_variables.each do |var|
|
21
|
+
qry.instance_variable_set(var, instance_variable_get(var))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def id(pid)
|
27
|
+
q QueryClause.id(pid)
|
28
|
+
limit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
def filter(*fltrs)
|
32
|
+
@filters.push *fltrs
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def fields(*flds)
|
37
|
+
@fields.push *flds
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def limit(num)
|
42
|
+
@rows = num
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def order_by(field, order)
|
47
|
+
@sort << [field, order].join(" ")
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def asc(field)
|
52
|
+
order_by field, "asc"
|
53
|
+
end
|
54
|
+
|
55
|
+
def desc(field)
|
56
|
+
order_by field, "desc"
|
57
|
+
end
|
58
|
+
|
59
|
+
def q(q)
|
60
|
+
@q = q
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def method_missing(name, *args, &block)
|
67
|
+
if Filter.respond_to? name
|
68
|
+
return filter Filter.send(name, *args, &block)
|
69
|
+
end
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|