ddr-models 2.4.12 → 2.4.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ddr-models.gemspec +1 -1
- data/lib/ddr/index.rb +0 -3
- data/lib/ddr/index/abstract_query_result.rb +2 -3
- data/lib/ddr/index/connection.rb +28 -9
- data/lib/ddr/index/csv_query_result.rb +31 -31
- data/lib/ddr/index/filter.rb +23 -10
- data/lib/ddr/index/query.rb +31 -5
- data/lib/ddr/index/query_builder.rb +14 -23
- data/lib/ddr/index/query_clause.rb +16 -1
- data/lib/ddr/index/query_result.rb +36 -4
- data/lib/ddr/index/response.rb +19 -2
- data/lib/ddr/models/solr_document.rb +1 -2
- data/lib/ddr/models/version.rb +1 -1
- data/spec/index/csv_query_result_spec.rb +44 -0
- data/spec/index/filter_spec.rb +53 -0
- data/spec/index/query_builder_spec.rb +25 -1
- data/spec/index/query_clause_spec.rb +10 -0
- data/spec/index/query_spec.rb +66 -23
- metadata +12 -7
- data/lib/ddr/index/csv_options.rb +0 -14
- data/lib/ddr/index/filters.rb +0 -26
- data/lib/ddr/index/solr_csv_options.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e305b209128c60e1cf1a0231c117686f834f491
|
4
|
+
data.tar.gz: c4fa26a45ebf460c892c9e5770dc2b10f2a326db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddd8c567e7ec34286dc13eba223a0dedb0b0db7773196b8cecbfa179c4e1c8cc44e6794692fd50deabf9afc37e116e6a35068b2b3fc6b13d525d6425c4201b76
|
7
|
+
data.tar.gz: a8139759bcd54585aa374f987598a8cdbfc27fabacb914ea841c980e271e384b1273ddd08d40c12f7724e3d836881435f9e09e40214dee42004f9a1ceff60c9d
|
data/ddr-models.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_dependency "cancancan", "~> 1.12"
|
34
34
|
s.add_dependency "ddr-antivirus", "~> 2.1.1"
|
35
35
|
s.add_dependency "virtus", "~> 1.0.5"
|
36
|
-
s.add_dependency "hashie", "~> 3.4.
|
36
|
+
s.add_dependency "hashie", "~> 3.4", "< 3.4.4"
|
37
37
|
|
38
38
|
s.add_development_dependency "bundler", "~> 1.11"
|
39
39
|
s.add_development_dependency "rake"
|
data/lib/ddr/index.rb
CHANGED
@@ -4,14 +4,12 @@ module Ddr
|
|
4
4
|
|
5
5
|
autoload :AbstractQueryResult
|
6
6
|
autoload :Connection
|
7
|
-
autoload :CSVOptions
|
8
7
|
autoload :CSVQueryResult
|
9
8
|
autoload :DocumentBuilder
|
10
9
|
autoload :Field
|
11
10
|
autoload :FieldAttribute
|
12
11
|
autoload :Fields
|
13
12
|
autoload :Filter
|
14
|
-
autoload :Filters
|
15
13
|
autoload :LegacyLicenseFields
|
16
14
|
autoload :Query
|
17
15
|
autoload :QueryBuilder
|
@@ -19,7 +17,6 @@ module Ddr
|
|
19
17
|
autoload :QueryParams
|
20
18
|
autoload :QueryResult
|
21
19
|
autoload :Response
|
22
|
-
autoload :SolrCSVOptions
|
23
20
|
autoload :SortOrder
|
24
21
|
autoload :UniqueKeyField
|
25
22
|
|
@@ -2,16 +2,15 @@ module Ddr::Index
|
|
2
2
|
class AbstractQueryResult
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
attr_reader :query
|
5
|
+
attr_reader :query
|
6
6
|
delegate :params, to: :query
|
7
7
|
|
8
8
|
def initialize(query)
|
9
9
|
@query = query.dup.freeze
|
10
|
-
@conn = Connection.new
|
11
10
|
end
|
12
11
|
|
13
12
|
def count
|
14
|
-
response =
|
13
|
+
response = Connection.select(params, rows: 0)
|
15
14
|
response.num_found
|
16
15
|
end
|
17
16
|
|
data/lib/ddr/index/connection.rb
CHANGED
@@ -1,17 +1,36 @@
|
|
1
|
+
require "rsolr"
|
2
|
+
require "forwardable"
|
3
|
+
|
1
4
|
module Ddr::Index
|
2
|
-
|
5
|
+
#
|
6
|
+
# Wraps an RSolr connection
|
7
|
+
#
|
8
|
+
class Connection
|
3
9
|
|
4
|
-
|
5
|
-
|
6
|
-
end
|
10
|
+
module Methods
|
11
|
+
extend Forwardable
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
delegate [:get, :paginate] => :solr
|
14
|
+
|
15
|
+
def solr
|
16
|
+
RSolr.connect(ActiveFedora.solr_config)
|
17
|
+
end
|
11
18
|
|
12
|
-
|
13
|
-
|
19
|
+
def select(params, extra={})
|
20
|
+
Response.new get("select", params: params.merge(extra))
|
21
|
+
end
|
22
|
+
|
23
|
+
def page(*args)
|
24
|
+
Response.new paginate(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def count(params)
|
28
|
+
select(params, rows: 0).num_found
|
29
|
+
end
|
14
30
|
end
|
15
31
|
|
32
|
+
extend Methods
|
33
|
+
include Methods
|
34
|
+
|
16
35
|
end
|
17
36
|
end
|
@@ -3,65 +3,65 @@ require "csv"
|
|
3
3
|
module Ddr::Index
|
4
4
|
class CSVQueryResult < AbstractQueryResult
|
5
5
|
|
6
|
-
MAX_ROWS
|
7
|
-
|
6
|
+
MAX_ROWS = 10**8 # Just set to a really high number :)
|
7
|
+
CSV_MV_SEPARATOR = ";"
|
8
8
|
|
9
|
-
|
9
|
+
delegate :headers, :to_s, :to_csv, to: :table
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(query, mv_sep: MV_SEP)
|
14
|
-
super(query)
|
15
|
-
@mv_sep = mv_sep
|
11
|
+
def delete_empty_columns!
|
12
|
+
table.by_col!.delete_if { |c, vals| vals.all?(&:nil?) }
|
16
13
|
end
|
17
14
|
|
18
|
-
def
|
19
|
-
|
15
|
+
def each(&block)
|
16
|
+
table.by_row!.each(&block)
|
20
17
|
end
|
21
18
|
|
22
|
-
def
|
23
|
-
|
19
|
+
def [](index_or_header)
|
20
|
+
table.by_col_or_row![index_or_header]
|
24
21
|
end
|
25
22
|
|
26
|
-
def
|
27
|
-
|
23
|
+
def table
|
24
|
+
@table ||= CSV.parse(data, csv_opts)
|
28
25
|
end
|
29
26
|
|
30
27
|
def csv_opts
|
31
|
-
|
28
|
+
{ headers: csv_headers,
|
29
|
+
return_headers: false,
|
30
|
+
write_headers: true,
|
31
|
+
}
|
32
32
|
end
|
33
33
|
|
34
34
|
def solr_csv_opts
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
{ "csv.mv.separator" => CSV_MV_SEPARATOR,
|
36
|
+
"csv.header" => solr_csv_header?,
|
37
|
+
"rows" => solr_csv_rows,
|
38
|
+
"wt" => "csv",
|
39
|
+
}
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
42
|
+
def query_field_headings
|
43
|
+
query.fields.map { |f| f.respond_to?(:heading) ? f.heading : f.to_s }
|
44
44
|
end
|
45
45
|
|
46
46
|
def csv_headers
|
47
|
-
|
48
|
-
:first_row
|
49
|
-
else
|
50
|
-
headers
|
51
|
-
end
|
47
|
+
query.fields.empty? ? :first_row : query_field_headings
|
52
48
|
end
|
53
49
|
|
54
|
-
def solr_csv_header
|
50
|
+
def solr_csv_header?
|
55
51
|
csv_headers == :first_row
|
56
52
|
end
|
57
53
|
|
54
|
+
def solr_csv_rows
|
55
|
+
query.rows || MAX_ROWS
|
56
|
+
end
|
57
|
+
|
58
58
|
def solr_csv_params
|
59
|
-
params.merge
|
59
|
+
params.merge(solr_csv_opts)
|
60
60
|
end
|
61
61
|
|
62
62
|
def data
|
63
|
-
raw =
|
64
|
-
raw.gsub(/\\#{
|
63
|
+
raw = Connection.get("select", params: solr_csv_params)
|
64
|
+
raw.gsub(/\\#{CSV_MV_SEPARATOR}/, CSV_MV_SEPARATOR)
|
65
65
|
end
|
66
66
|
|
67
67
|
end
|
data/lib/ddr/index/filter.rb
CHANGED
@@ -57,6 +57,16 @@ module Ddr::Index
|
|
57
57
|
self.clauses << QueryClause.before_days(field, value)
|
58
58
|
self
|
59
59
|
end
|
60
|
+
|
61
|
+
def join(**args)
|
62
|
+
self.clauses << QueryClause.join(**args)
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def regexp(field, value)
|
67
|
+
self.clauses << QueryClause.regexp(field, value)
|
68
|
+
self
|
69
|
+
end
|
60
70
|
end
|
61
71
|
|
62
72
|
module ClassMethods
|
@@ -68,16 +78,16 @@ module Ddr::Index
|
|
68
78
|
model "Component", "Attachment", "Target"
|
69
79
|
end
|
70
80
|
|
71
|
-
def is_governed_by(
|
72
|
-
term is_governed_by:
|
81
|
+
def is_governed_by(arg)
|
82
|
+
term is_governed_by: get_uri(arg)
|
73
83
|
end
|
74
84
|
|
75
|
-
def is_member_of_collection(
|
76
|
-
term is_member_of_collection:
|
85
|
+
def is_member_of_collection(arg)
|
86
|
+
term is_member_of_collection: get_uri(arg)
|
77
87
|
end
|
78
88
|
|
79
|
-
def is_part_of(
|
80
|
-
term is_part_of:
|
89
|
+
def is_part_of(arg)
|
90
|
+
term is_part_of: get_uri(arg)
|
81
91
|
end
|
82
92
|
|
83
93
|
def model(*models)
|
@@ -86,11 +96,14 @@ module Ddr::Index
|
|
86
96
|
|
87
97
|
private
|
88
98
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
99
|
+
def get_uri(arg)
|
100
|
+
case arg
|
101
|
+
when ActiveFedora::Base
|
102
|
+
arg.internal_uri
|
103
|
+
when String
|
104
|
+
arg.start_with?("info:fedora/") ? arg : "info:fedora/#{arg}"
|
92
105
|
else
|
93
|
-
ActiveFedora::Base.
|
106
|
+
raise TypeError, "Argument must be a String or ActiveFedora::Base instance: #{arg.class}"
|
94
107
|
end
|
95
108
|
end
|
96
109
|
|
data/lib/ddr/index/query.rb
CHANGED
@@ -5,6 +5,7 @@ module Ddr::Index
|
|
5
5
|
class Query
|
6
6
|
include Virtus.model
|
7
7
|
extend Forwardable
|
8
|
+
extend Deprecation
|
8
9
|
|
9
10
|
attribute :q, String
|
10
11
|
attribute :fields, Array[FieldAttribute], default: [ ]
|
@@ -12,9 +13,15 @@ module Ddr::Index
|
|
12
13
|
attribute :sort, Array[String], default: [ ]
|
13
14
|
attribute :rows, Integer
|
14
15
|
|
15
|
-
delegate [:count, :docs, :
|
16
|
+
delegate [:count, :docs, :ids, :each_id, :all] => :result
|
16
17
|
delegate :params => :query_params
|
17
18
|
|
19
|
+
def self.build(*args, &block)
|
20
|
+
new.tap do |query|
|
21
|
+
query.build(*args, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
def initialize(**args, &block)
|
19
26
|
super(**args)
|
20
27
|
if block_given?
|
@@ -31,12 +38,22 @@ module Ddr::Index
|
|
31
38
|
URI.encode_www_form(params)
|
32
39
|
end
|
33
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
|
+
|
34
51
|
def result
|
35
52
|
QueryResult.new(self)
|
36
53
|
end
|
37
54
|
|
38
|
-
def csv
|
39
|
-
CSVQueryResult.new(self
|
55
|
+
def csv
|
56
|
+
CSVQueryResult.new(self)
|
40
57
|
end
|
41
58
|
|
42
59
|
def filter_clauses
|
@@ -47,10 +64,19 @@ module Ddr::Index
|
|
47
64
|
QueryParams.new(self)
|
48
65
|
end
|
49
66
|
|
50
|
-
def build(&block)
|
51
|
-
QueryBuilder.new(self, &block)
|
67
|
+
def build(*args, &block)
|
68
|
+
QueryBuilder.new(self, *args, &block)
|
52
69
|
self
|
53
70
|
end
|
54
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
|
+
|
55
81
|
end
|
56
82
|
end
|
@@ -28,9 +28,6 @@ module Ddr::Index
|
|
28
28
|
#
|
29
29
|
# See also: asc, order_by
|
30
30
|
#
|
31
|
-
# id [doc_id]
|
32
|
-
# For selecting a single document by ID.
|
33
|
-
#
|
34
31
|
# filter [filter1], ...
|
35
32
|
# Adds filters to the query.
|
36
33
|
#
|
@@ -48,6 +45,12 @@ module Ddr::Index
|
|
48
45
|
# fields [field], ...
|
49
46
|
# Alias for: field
|
50
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
|
+
#
|
51
54
|
# limit [int]
|
52
55
|
# Limits the number of documents returned by the query.
|
53
56
|
#
|
@@ -74,6 +77,11 @@ module Ddr::Index
|
|
74
77
|
# raw [clause1], ...
|
75
78
|
# Adds a filter of "raw" query clauses (i.e., pre-constructed).
|
76
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
|
+
#
|
77
85
|
# rows [int]
|
78
86
|
# Alias for: limit
|
79
87
|
#
|
@@ -91,24 +99,12 @@ module Ddr::Index
|
|
91
99
|
#
|
92
100
|
class QueryBuilder
|
93
101
|
|
94
|
-
# Builds a Query object
|
95
|
-
# @yield [builder] a new QueryBuilder instance.
|
96
|
-
# @return [Query]
|
97
|
-
def self.build
|
98
|
-
Deprecation.warn(self,
|
99
|
-
"`Ddr::Index::QueryBuilder.build` is deprecated and will be removed in ddr-models 3.0." \
|
100
|
-
" Use `Ddr::Index::QueryBuilder.new` instead.")
|
101
|
-
builder = new
|
102
|
-
yield builder
|
103
|
-
builder.query
|
104
|
-
end
|
105
|
-
|
106
102
|
attr_reader :query
|
107
103
|
|
108
|
-
def initialize(
|
109
|
-
@query =
|
104
|
+
def initialize(*args, &block)
|
105
|
+
@query = args.first.is_a?(Query) ? args.shift : Query.new
|
110
106
|
if block_given?
|
111
|
-
|
107
|
+
instance_exec(*args, &block)
|
112
108
|
end
|
113
109
|
end
|
114
110
|
|
@@ -146,11 +142,6 @@ module Ddr::Index
|
|
146
142
|
# @param orderings [Hash<Field, String>]
|
147
143
|
# @return [QueryBuilder] self
|
148
144
|
def order_by(*orderings)
|
149
|
-
unless orderings.first.is_a? Hash
|
150
|
-
Deprecation.warn(QueryBuilder, "`order_by` will require a hash of orderings in ddr-models 3.0.")
|
151
|
-
field, order = orderings
|
152
|
-
return order_by(field => order)
|
153
|
-
end
|
154
145
|
query.sort += orderings.first.map { |field, order| SortOrder.new(field: field, order: order) }
|
155
146
|
self
|
156
147
|
end
|
@@ -12,6 +12,7 @@ module Ddr::Index
|
|
12
12
|
STANDARD_QUERY = "%{field}:%{value}"
|
13
13
|
NEGATIVE_QUERY = "-%{field}:%{value}"
|
14
14
|
DISJUNCTION = "{!lucene q.op=OR df=%{field}}%{value}"
|
15
|
+
REGEXP_QUERY = "%{field}:/%{value}/"
|
15
16
|
|
16
17
|
values do
|
17
18
|
attribute :field, FieldAttribute
|
@@ -29,7 +30,6 @@ module Ddr::Index
|
|
29
30
|
end
|
30
31
|
|
31
32
|
class << self
|
32
|
-
|
33
33
|
def quote(value)
|
34
34
|
# Derived from Blacklight::Solr::SearchBuilderBehavior#solr_param_quote
|
35
35
|
unless value =~ /\A[a-zA-Z0-9$_\-\^]+\z/
|
@@ -75,6 +75,16 @@ module Ddr::Index
|
|
75
75
|
new(field: field, value: value, template: DISJUNCTION)
|
76
76
|
end
|
77
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
|
+
|
78
88
|
# Builds a query clause to filter where date field value is earlier than a date/time value.
|
79
89
|
def before(field, value)
|
80
90
|
new(field: field, value: "[* TO %s]" % Ddr::Utils.solr_date(value))
|
@@ -91,6 +101,11 @@ module Ddr::Index
|
|
91
101
|
new(field: field, value: value, template: TERM_QUERY)
|
92
102
|
end
|
93
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
|
94
109
|
end
|
95
110
|
|
96
111
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Ddr::Index
|
2
2
|
class QueryResult < AbstractQueryResult
|
3
|
+
extend Deprecation
|
3
4
|
|
4
5
|
PAGE_SIZE = 1000
|
5
6
|
|
@@ -14,7 +15,7 @@ module Ddr::Index
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def each_unpaginated(&block)
|
17
|
-
|
18
|
+
Connection.select(params).docs.each(&block)
|
18
19
|
end
|
19
20
|
|
20
21
|
def each_paginated(&block)
|
@@ -22,15 +23,31 @@ module Ddr::Index
|
|
22
23
|
end
|
23
24
|
|
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
|
25
34
|
Enumerator.new do |e|
|
26
35
|
each do |doc|
|
27
|
-
e << doc[Fields::
|
36
|
+
e << doc[Fields::ID]
|
28
37
|
end
|
29
38
|
end
|
30
39
|
end
|
31
40
|
|
32
41
|
def each_pid(&block)
|
33
|
-
|
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)
|
34
51
|
end
|
35
52
|
|
36
53
|
def docs
|
@@ -41,6 +58,21 @@ module Ddr::Index
|
|
41
58
|
end
|
42
59
|
end
|
43
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
|
+
|
44
76
|
def all
|
45
77
|
to_a
|
46
78
|
end
|
@@ -62,7 +94,7 @@ module Ddr::Index
|
|
62
94
|
def page(num)
|
63
95
|
page_params = params.dup
|
64
96
|
page_size = page_params.delete(:rows) || PAGE_SIZE
|
65
|
-
response =
|
97
|
+
response = Connection.page(num, page_size, "select", params: page_params)
|
66
98
|
response.docs
|
67
99
|
end
|
68
100
|
|
data/lib/ddr/index/response.rb
CHANGED
@@ -1,12 +1,29 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
1
3
|
module Ddr::Index
|
4
|
+
#
|
5
|
+
# Wraps an index query response
|
6
|
+
#
|
2
7
|
class Response < SimpleDelegator
|
3
8
|
|
4
9
|
def docs
|
5
|
-
|
10
|
+
response["docs"]
|
6
11
|
end
|
7
12
|
|
8
13
|
def num_found
|
9
|
-
|
14
|
+
response["numFound"].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def facet_counts
|
18
|
+
self["facet_counts"] || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def facet_fields
|
22
|
+
facet_counts["facet_fields"] || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def response
|
26
|
+
self["response"]
|
10
27
|
end
|
11
28
|
|
12
29
|
end
|
@@ -12,8 +12,7 @@ module Ddr::Models
|
|
12
12
|
|
13
13
|
module ClassMethods
|
14
14
|
def find(pid_or_uri)
|
15
|
-
|
16
|
-
query = Ddr::Index::QueryBuilder.build { |q| q.id(pid) }
|
15
|
+
query = Ddr::Index::Query.new { id pid_or_uri.sub(/\Ainfo:fedora\//, "") }
|
17
16
|
if doc = query.docs.first
|
18
17
|
return doc
|
19
18
|
end
|
data/lib/ddr/models/version.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Ddr::Index
|
2
|
+
RSpec.describe CSVQueryResult do
|
3
|
+
|
4
|
+
subject { described_class.new(query) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Item.create(title: ["Testing 1"],
|
8
|
+
identifier: ["test1"],
|
9
|
+
description: ["The process of eliminating errors."])
|
10
|
+
Item.create(title: ["Testing 2"],
|
11
|
+
identifier: ["test2"])
|
12
|
+
Item.create(title: ["Testing 3"])
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:query) {
|
16
|
+
Ddr::Index::Query.new do
|
17
|
+
fields Ddr::Index::Fields::ID
|
18
|
+
fields Ddr::Index::Fields.descmd
|
19
|
+
end
|
20
|
+
}
|
21
|
+
|
22
|
+
specify {
|
23
|
+
expect(subject["title"]).to contain_exactly("Testing 1", "Testing 2", "Testing 3")
|
24
|
+
expect(subject["identifier"]).to contain_exactly("test1", "test2", nil)
|
25
|
+
expect(subject["description"]).to contain_exactly("The process of eliminating errors.", nil, nil)
|
26
|
+
expect(subject["creator"]).to contain_exactly(nil, nil, nil)
|
27
|
+
expect(subject.headers).to include("creator")
|
28
|
+
expect(subject.to_s).to match(/creator/)
|
29
|
+
}
|
30
|
+
|
31
|
+
describe "#delete_empty_columns!" do
|
32
|
+
specify {
|
33
|
+
subject.delete_empty_columns!
|
34
|
+
expect(subject["title"]).to contain_exactly("Testing 1", "Testing 2", "Testing 3")
|
35
|
+
expect(subject["identifier"]).to contain_exactly("test1", "test2", nil)
|
36
|
+
expect(subject["description"]).to contain_exactly("The process of eliminating errors.", nil, nil)
|
37
|
+
expect(subject["creator"]).to contain_exactly(nil, nil, nil)
|
38
|
+
expect(subject.headers).to contain_exactly("pid", "title", "identifier", "description")
|
39
|
+
expect(subject.to_s).not_to match(/creator/)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/spec/index/filter_spec.rb
CHANGED
@@ -37,6 +37,12 @@ module Ddr::Index
|
|
37
37
|
are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
|
38
38
|
}
|
39
39
|
end
|
40
|
+
describe "with a URI" do
|
41
|
+
subject { described_class.is_governed_by("info:fedora/test:1") }
|
42
|
+
its(:clauses) {
|
43
|
+
are_expected.to eq([QueryClause.term(:is_governed_by, "info:fedora/test:1")])
|
44
|
+
}
|
45
|
+
end
|
40
46
|
end
|
41
47
|
describe ".is_member_of_collection" do
|
42
48
|
describe "with an object" do
|
@@ -51,6 +57,32 @@ module Ddr::Index
|
|
51
57
|
are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
|
52
58
|
}
|
53
59
|
end
|
60
|
+
describe "with a URI" do
|
61
|
+
subject { described_class.is_member_of_collection("info:fedora/test:1") }
|
62
|
+
its(:clauses) {
|
63
|
+
are_expected.to eq([QueryClause.term(:is_member_of_collection, "info:fedora/test:1")])
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
describe ".is_part_of" do
|
68
|
+
describe "with an object" do
|
69
|
+
subject { described_class.is_part_of(Item.new(pid: "test:1")) }
|
70
|
+
its(:clauses) {
|
71
|
+
are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
|
72
|
+
}
|
73
|
+
end
|
74
|
+
describe "with an ID" do
|
75
|
+
subject { described_class.is_part_of("test:1") }
|
76
|
+
its(:clauses) {
|
77
|
+
are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
|
78
|
+
}
|
79
|
+
end
|
80
|
+
describe "with a URI" do
|
81
|
+
subject { described_class.is_part_of("info:fedora/test:1") }
|
82
|
+
its(:clauses) {
|
83
|
+
are_expected.to eq([QueryClause.term(:is_part_of, "info:fedora/test:1")])
|
84
|
+
}
|
85
|
+
end
|
54
86
|
end
|
55
87
|
describe ".has_content" do
|
56
88
|
subject { described_class.has_content }
|
@@ -107,6 +139,20 @@ module Ddr::Index
|
|
107
139
|
are_expected.to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
|
108
140
|
}
|
109
141
|
end
|
142
|
+
describe ".join" do
|
143
|
+
subject {
|
144
|
+
described_class.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})
|
145
|
+
}
|
146
|
+
its(:clauses) {
|
147
|
+
are_expected.to eq([QueryClause.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})])
|
148
|
+
}
|
149
|
+
end
|
150
|
+
describe ".regexp" do
|
151
|
+
subject { described_class.regexp("foo", "foo/bar.*") }
|
152
|
+
its(:clauses) {
|
153
|
+
are_expected.to eq([QueryClause.regexp("foo", "foo/bar.*")])
|
154
|
+
}
|
155
|
+
end
|
110
156
|
end
|
111
157
|
|
112
158
|
describe "API methods" do
|
@@ -166,6 +212,13 @@ module Ddr::Index
|
|
166
212
|
expect(subject.clauses).to eq([QueryClause.before("foo", DateTime.parse("Thu, 27 Aug 2015 17:42:34 -0400"))])
|
167
213
|
end
|
168
214
|
end
|
215
|
+
describe "#join" do
|
216
|
+
it "adds a join query clause" do
|
217
|
+
subject.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})
|
218
|
+
expect(subject.clauses).to eq([QueryClause.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})])
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
169
222
|
end
|
170
223
|
|
171
224
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Ddr::Index
|
2
2
|
RSpec.describe QueryBuilder do
|
3
|
-
|
4
3
|
describe "DSL" do
|
5
4
|
describe "id" do
|
6
5
|
subject { described_class.new { id "test:1" } }
|
@@ -95,6 +94,22 @@ module Ddr::Index
|
|
95
94
|
subject { described_class.new { before_days "foo", 7 } }
|
96
95
|
specify { expect(subject.query.filters).to eq [Filter.before_days("foo", 7)] }
|
97
96
|
end
|
97
|
+
describe "join" do
|
98
|
+
subject {
|
99
|
+
described_class.new do
|
100
|
+
join from: :id, to: :collection_uri, where: {admin_set: "dvs"}
|
101
|
+
end
|
102
|
+
}
|
103
|
+
specify {
|
104
|
+
expect(subject.query.filters).to eq [Filter.join(from: :id, to: :collection_uri, where: {admin_set: "dvs"})]
|
105
|
+
}
|
106
|
+
end
|
107
|
+
describe "regexp" do
|
108
|
+
subject { described_class.new { regexp "foo", "foo/bar.*" } }
|
109
|
+
specify {
|
110
|
+
expect(subject.query.filters).to eq [Filter.regexp("foo", "foo/bar.*")]
|
111
|
+
}
|
112
|
+
end
|
98
113
|
end
|
99
114
|
|
100
115
|
describe "using static filters" do
|
@@ -112,5 +127,14 @@ module Ddr::Index
|
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
130
|
+
describe "passing local vars" do
|
131
|
+
let(:local_var) { double(bar: "bar") }
|
132
|
+
subject {
|
133
|
+
described_class.new(local_var) { |foo| asc foo.bar }
|
134
|
+
}
|
135
|
+
specify {
|
136
|
+
expect(subject.query.sort).to eq [SortOrder.asc("bar")]
|
137
|
+
}
|
138
|
+
end
|
115
139
|
end
|
116
140
|
end
|
@@ -52,6 +52,16 @@ module Ddr::Index
|
|
52
52
|
its(:to_s) { is_expected.to eq "{!lucene q.op=OR df=foo}\"Jungle Fever\" bar" }
|
53
53
|
end
|
54
54
|
end
|
55
|
+
describe ".join" do
|
56
|
+
subject {
|
57
|
+
described_class.join(from: :id, to: :collection_uri, where: { admin_set: "dvs"})
|
58
|
+
}
|
59
|
+
its(:to_s) { is_expected.to eq "{!join from=id to=collection_uri_ssim}admin_set_ssi:dvs" }
|
60
|
+
end
|
61
|
+
describe ".regexp" do
|
62
|
+
subject { described_class.regexp("foo", "foo/bar.*") }
|
63
|
+
its(:to_s) { is_expected.to eq "foo:/foo\\/bar.*/" }
|
64
|
+
end
|
55
65
|
end
|
56
66
|
|
57
67
|
end
|
data/spec/index/query_spec.rb
CHANGED
@@ -1,20 +1,16 @@
|
|
1
1
|
module Ddr::Index
|
2
2
|
RSpec.describe Query do
|
3
|
-
|
4
|
-
|
5
|
-
let(:
|
6
|
-
let(:foo) { Field.new("foo") }
|
7
|
-
let(:spam) { Field.new("spam") }
|
8
|
-
let(:filter) { Filter.where(spam=>"eggs") }
|
9
|
-
let(:sort_order) { SortOrder.new(field: foo, order: "asc") }
|
10
|
-
let(:fields) { [id, foo, spam] }
|
11
|
-
|
3
|
+
describe ".build" do
|
4
|
+
let(:local1) { double(value: "foo:bar") }
|
5
|
+
let(:local2) { double(value: "foo") }
|
12
6
|
subject {
|
13
|
-
described_class.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
7
|
+
described_class.build(local1, local2) do |l1, l2|
|
8
|
+
q l1.value
|
9
|
+
where "spam"=>"eggs"
|
10
|
+
fields :id, "foo", "spam"
|
11
|
+
asc l2.value
|
12
|
+
limit 50
|
13
|
+
end
|
18
14
|
}
|
19
15
|
|
20
16
|
its(:to_s) {
|
@@ -25,7 +21,52 @@ module Ddr::Index
|
|
25
21
|
}
|
26
22
|
end
|
27
23
|
|
28
|
-
describe "
|
24
|
+
describe "initialization" do
|
25
|
+
describe "with attributes" do
|
26
|
+
let(:id) { UniqueKeyField.instance }
|
27
|
+
let(:foo) { Field.new("foo") }
|
28
|
+
let(:spam) { Field.new("spam") }
|
29
|
+
let(:filter) { Filter.where(spam=>"eggs") }
|
30
|
+
let(:sort_order) { SortOrder.new(field: foo, order: "asc") }
|
31
|
+
let(:fields) { [id, foo, spam] }
|
32
|
+
|
33
|
+
subject {
|
34
|
+
described_class.new(q: "foo:bar",
|
35
|
+
filters: [filter],
|
36
|
+
fields: fields,
|
37
|
+
sort: sort_order,
|
38
|
+
rows: 50)
|
39
|
+
}
|
40
|
+
|
41
|
+
its(:to_s) {
|
42
|
+
is_expected.to eq "q=foo%3Abar&fq=spam%3Aeggs&fl=id%2Cfoo%2Cspam&sort=foo+asc&rows=50"
|
43
|
+
}
|
44
|
+
its(:params) {
|
45
|
+
is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["spam:eggs"], sort: "foo asc", rows: 50})
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with a block" do
|
50
|
+
subject {
|
51
|
+
described_class.new do
|
52
|
+
q "foo:bar"
|
53
|
+
where "spam"=>"eggs"
|
54
|
+
fields :id, "foo", "spam"
|
55
|
+
asc "foo"
|
56
|
+
limit 50
|
57
|
+
end
|
58
|
+
}
|
59
|
+
|
60
|
+
its(:to_s) {
|
61
|
+
is_expected.to eq "q=foo%3Abar&fq=spam%3Aeggs&fl=id%2Cfoo%2Cspam&sort=foo+asc&rows=50"
|
62
|
+
}
|
63
|
+
its(:params) {
|
64
|
+
is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["spam:eggs"], sort: "foo asc", rows: 50})
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "equality" do
|
29
70
|
subject {
|
30
71
|
described_class.new do
|
31
72
|
q "foo:bar"
|
@@ -35,14 +76,16 @@ module Ddr::Index
|
|
35
76
|
limit 50
|
36
77
|
end
|
37
78
|
}
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
79
|
+
let(:other) do
|
80
|
+
described_class.new do
|
81
|
+
q "foo:bar"
|
82
|
+
where "spam"=>"eggs"
|
83
|
+
fields :id, "foo", "spam"
|
84
|
+
asc "foo"
|
85
|
+
limit 50
|
86
|
+
end
|
87
|
+
end
|
88
|
+
it { is_expected.to eq other }
|
45
89
|
end
|
46
|
-
|
47
90
|
end
|
48
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddr-models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4.
|
4
|
+
version: 2.4.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Coble
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-09-
|
12
|
+
date: 2016-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -227,14 +227,20 @@ dependencies:
|
|
227
227
|
requirements:
|
228
228
|
- - "~>"
|
229
229
|
- !ruby/object:Gem::Version
|
230
|
-
version: 3.4
|
230
|
+
version: '3.4'
|
231
|
+
- - "<"
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: 3.4.4
|
231
234
|
type: :runtime
|
232
235
|
prerelease: false
|
233
236
|
version_requirements: !ruby/object:Gem::Requirement
|
234
237
|
requirements:
|
235
238
|
- - "~>"
|
236
239
|
- !ruby/object:Gem::Version
|
237
|
-
version: 3.4
|
240
|
+
version: '3.4'
|
241
|
+
- - "<"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: 3.4.4
|
238
244
|
- !ruby/object:Gem::Dependency
|
239
245
|
name: bundler
|
240
246
|
requirement: !ruby/object:Gem::Requirement
|
@@ -473,14 +479,12 @@ files:
|
|
473
479
|
- lib/ddr/index.rb
|
474
480
|
- lib/ddr/index/abstract_query_result.rb
|
475
481
|
- lib/ddr/index/connection.rb
|
476
|
-
- lib/ddr/index/csv_options.rb
|
477
482
|
- lib/ddr/index/csv_query_result.rb
|
478
483
|
- lib/ddr/index/document_builder.rb
|
479
484
|
- lib/ddr/index/field.rb
|
480
485
|
- lib/ddr/index/field_attribute.rb
|
481
486
|
- lib/ddr/index/fields.rb
|
482
487
|
- lib/ddr/index/filter.rb
|
483
|
-
- lib/ddr/index/filters.rb
|
484
488
|
- lib/ddr/index/legacy_license_fields.rb
|
485
489
|
- lib/ddr/index/query.rb
|
486
490
|
- lib/ddr/index/query_builder.rb
|
@@ -488,7 +492,6 @@ files:
|
|
488
492
|
- lib/ddr/index/query_params.rb
|
489
493
|
- lib/ddr/index/query_result.rb
|
490
494
|
- lib/ddr/index/response.rb
|
491
|
-
- lib/ddr/index/solr_csv_options.rb
|
492
495
|
- lib/ddr/index/sort_order.rb
|
493
496
|
- lib/ddr/index/unique_key_field.rb
|
494
497
|
- lib/ddr/jobs.rb
|
@@ -647,6 +650,7 @@ files:
|
|
647
650
|
- spec/fixtures/sample.pdf
|
648
651
|
- spec/fixtures/target.png
|
649
652
|
- spec/helpers/models_helper_spec.rb
|
653
|
+
- spec/index/csv_query_result_spec.rb
|
650
654
|
- spec/index/fields_spec.rb
|
651
655
|
- spec/index/filter_spec.rb
|
652
656
|
- spec/index/query_builder_spec.rb
|
@@ -823,6 +827,7 @@ test_files:
|
|
823
827
|
- spec/fixtures/sample.pdf
|
824
828
|
- spec/fixtures/target.png
|
825
829
|
- spec/helpers/models_helper_spec.rb
|
830
|
+
- spec/index/csv_query_result_spec.rb
|
826
831
|
- spec/index/fields_spec.rb
|
827
832
|
- spec/index/filter_spec.rb
|
828
833
|
- spec/index/query_builder_spec.rb
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require "csv"
|
2
|
-
require "hashie"
|
3
|
-
|
4
|
-
module Ddr::Index
|
5
|
-
class CSVOptions < Hashie::Dash
|
6
|
-
|
7
|
-
property :headers, default: CSV::DEFAULT_OPTIONS[:headers]
|
8
|
-
property :return_headers, default: true
|
9
|
-
property :write_headers, default: true
|
10
|
-
property :col_sep, default: CSV::DEFAULT_OPTIONS[:col_sep]
|
11
|
-
property :quote_char, default: CSV::DEFAULT_OPTIONS[:quote_char]
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
data/lib/ddr/index/filters.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Ddr::Index
|
2
|
-
module Filters
|
3
|
-
extend Deprecation
|
4
|
-
|
5
|
-
def self.is_governed_by(pid)
|
6
|
-
Deprecation.warn(self,
|
7
|
-
"`Ddr::Index:Filters.is_governed_by` is deprecated and will be removed in ddr-models 3.0." \
|
8
|
-
" Use `Ddr::Index::Filter.is_governed_by` instead.")
|
9
|
-
Filter.is_governed_by(pid)
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def self.const_missing(name)
|
15
|
-
if name == :HAS_CONTENT
|
16
|
-
Deprecation.warn(self,
|
17
|
-
"`Ddr::Index::Filters::#{name}` is deprecated and will be removed in ddr-models 3.0." \
|
18
|
-
" Use `Ddr::Index::Filter.has_content` instead.")
|
19
|
-
Filter.has_content
|
20
|
-
else
|
21
|
-
super
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require "hashie"
|
2
|
-
|
3
|
-
module Ddr::Index
|
4
|
-
class SolrCSVOptions < Hashie::Trash
|
5
|
-
|
6
|
-
property "csv.header", from: :header, default: false
|
7
|
-
property "csv.separator", from: :col_sep, default: ","
|
8
|
-
property "csv.encapsulator", from: :quote_char, default: '"'
|
9
|
-
property "csv.mv.separator", from: :mv_sep, default: ","
|
10
|
-
property :wt, default: "csv"
|
11
|
-
property :rows
|
12
|
-
|
13
|
-
def params
|
14
|
-
to_h.reject { |k, v| v.nil? }
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|