activedocument 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
@@ -221,7 +221,12 @@ module ActiveDocument
|
|
221
221
|
else
|
222
222
|
root_namespace = namespace_for_element(root)
|
223
223
|
end
|
224
|
-
|
224
|
+
if arguments[6]
|
225
|
+
options = arguments[6]
|
226
|
+
else
|
227
|
+
options = nil
|
228
|
+
end
|
229
|
+
execute_attribute_finder(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace, options)
|
225
230
|
elsif method =~ /find_by_(.*)$/ and arguments.length > 0 # identify element search methods
|
226
231
|
value = arguments[0]
|
227
232
|
element = $1.to_sym
|
@@ -240,7 +245,14 @@ module ActiveDocument
|
|
240
245
|
else
|
241
246
|
root_namespace = namespace_for_element(root)
|
242
247
|
end
|
243
|
-
|
248
|
+
if arguments[4]
|
249
|
+
options = arguments[4]
|
250
|
+
else
|
251
|
+
options = nil
|
252
|
+
end
|
253
|
+
execute_finder(element, value, root, element_namespace, root_namespace, options)
|
254
|
+
else
|
255
|
+
super
|
244
256
|
end
|
245
257
|
|
246
258
|
end
|
@@ -49,14 +49,14 @@ module ActiveDocument
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
def self.execute_finder(element, value, root = nil, element_namespace = nil, root_namespace = nil)
|
53
|
-
xquery = @@xquery_builder.find_by_element(element, value, root, element_namespace, root_namespace)
|
52
|
+
def self.execute_finder(element, value, root = nil, element_namespace = nil, root_namespace = nil, options = nil)
|
53
|
+
xquery = @@xquery_builder.find_by_element(element, value, root, element_namespace, root_namespace, options)
|
54
54
|
@@log.info("Finder.execute_finder at line #{__LINE__}: #{xquery}")
|
55
55
|
SearchResults.new(@@ml_http.send_xquery(xquery))
|
56
56
|
end
|
57
57
|
|
58
|
-
def self.execute_attribute_finder(element, attribute, value, root = nil, element_namespace = nil, attribute_namespace = nil, root_namespace = nil)
|
59
|
-
xquery = @@xquery_builder.find_by_attribute(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace)
|
58
|
+
def self.execute_attribute_finder(element, attribute, value, root = nil, element_namespace = nil, attribute_namespace = nil, root_namespace = nil, options = nil)
|
59
|
+
xquery = @@xquery_builder.find_by_attribute(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace, options)
|
60
60
|
@@log.info("Finder.execute_attribute_finder at line #{__LINE__}: #{xquery}")
|
61
61
|
SearchResults.new(@@ml_http.send_xquery(xquery))
|
62
62
|
end
|
@@ -11,7 +11,7 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
|
-
|
14
|
+
require 'ActiveDocument/mark_logic_search_options'
|
15
15
|
module ActiveDocument
|
16
16
|
# todo create new unit tests for this class - the old ones were no good
|
17
17
|
class MarkLogicQueryBuilder
|
@@ -26,77 +26,47 @@ module ActiveDocument
|
|
26
26
|
|
27
27
|
def save(document, uri)
|
28
28
|
xquery = <<-GENERATED
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
GENERATED
|
35
|
-
|
29
|
+
xdmp:document-insert(
|
30
|
+
"#{uri}",
|
31
|
+
#{document.to_s} ,
|
32
|
+
xdmp:default-permissions(),
|
33
|
+
xdmp:default-collections())
|
34
|
+
GENERATED
|
36
35
|
end
|
37
36
|
|
38
37
|
# This method does a full text search
|
39
|
-
def find_by_word(word, root,
|
38
|
+
def find_by_word(word, root, root_namespace, options = nil)
|
40
39
|
xquery = <<-GENERATED
|
41
|
-
import module namespace search = "http://marklogic.com/appservices/search"at "/MarkLogic/appservices/search/search.xqy";
|
40
|
+
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
|
42
41
|
search:search("#{word}",
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
xquery << " xmlns:a=\"#{namespace}\"" unless namespace.nil? or namespace.empty?
|
49
|
-
xquery << '>/'
|
50
|
-
xquery << "a:" unless namespace.nil? or namespace.empty?
|
51
|
-
xquery << "#{root}</searchable-expression>"
|
52
|
-
end
|
53
|
-
xquery << "</options>)"
|
42
|
+
GENERATED
|
43
|
+
search_options = setup_options(options, root, root_namespace)
|
44
|
+
xquery << search_options.to_s
|
45
|
+
xquery << ')'
|
54
46
|
end
|
55
47
|
|
56
|
-
def find_by_element(element, value, root, element_namespace, root_namespace)
|
48
|
+
def find_by_element(element, value, root, element_namespace, root_namespace, options = nil)
|
57
49
|
xquery = <<-GENERATED
|
58
50
|
import module namespace search = "http://marklogic.com/appservices/search"at "/MarkLogic/appservices/search/search.xqy";
|
59
|
-
search:search("
|
60
|
-
<options xmlns="http://marklogic.com/appservices/search">
|
51
|
+
search:search('find_by_element:\"#{value}\"',
|
61
52
|
GENERATED
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
xquery << "a:" unless root_namespace.nil?
|
67
|
-
xquery << "#{root}</searchable-expression>"
|
68
|
-
end
|
69
|
-
xquery << <<-CONSTRAINT
|
70
|
-
<constraint name="word">
|
71
|
-
<word>
|
72
|
-
<element ns="#{element_namespace unless element_namespace.nil?}" name="#{element}"/>
|
73
|
-
</word>
|
74
|
-
</constraint></options>)
|
75
|
-
CONSTRAINT
|
53
|
+
search_options = setup_options(options, root, root_namespace)
|
54
|
+
search_options.word_constraints["find_by_element"] = {"namespace" => element_namespace, "element" => element}
|
55
|
+
xquery << search_options.to_s
|
56
|
+
xquery << ')'
|
76
57
|
end
|
77
58
|
|
78
|
-
|
79
|
-
|
59
|
+
|
60
|
+
def find_by_attribute(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace, options = nil)
|
80
61
|
xquery = <<-GENERATED
|
81
|
-
import module namespace search = "http://marklogic.com/appservices/search"at "/MarkLogic/appservices/search/search.xqy";
|
82
|
-
search:search("
|
83
|
-
<options xmlns="http://marklogic.com/appservices/search">
|
62
|
+
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
|
63
|
+
search:search("attribute:#{value}",
|
84
64
|
GENERATED
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
xquery << "#{root}</searchable-expression>"
|
91
|
-
end
|
92
|
-
xquery << <<-CONSTRAINT
|
93
|
-
<constraint name="word">
|
94
|
-
<word>
|
95
|
-
<attribute ns="#{attribute_namespace unless attribute_namespace.nil?}" name="#{attribute}"/>
|
96
|
-
<element ns="#{element_namespace unless element_namespace.nil?}" name="#{element}"/>
|
97
|
-
</word>
|
98
|
-
</constraint></options>)
|
99
|
-
CONSTRAINT
|
65
|
+
search_options = setup_options(options, root, root_namespace)
|
66
|
+
attribute_constraint = ActiveDocument::MarkLogicSearchOptions::AttributeConstraint.new(attribute_namespace, attribute, element_namespace, element)
|
67
|
+
search_options.attribute_constraints["attribute"] = attribute_constraint
|
68
|
+
xquery << search_options.to_s
|
69
|
+
xquery << ')'
|
100
70
|
end
|
101
71
|
|
102
72
|
def search(search_text, start, page_length, options)
|
@@ -106,23 +76,36 @@ GENERATED
|
|
106
76
|
option = options.to_s
|
107
77
|
end
|
108
78
|
<<-GENERATED
|
109
|
-
import module namespace search = "http://marklogic.com/appservices/search"at "/MarkLogic/appservices/search/search.xqy";
|
110
|
-
search:search('#{search_text}'
|
79
|
+
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
|
80
|
+
search:search('#{search_text}', #{option}, #{start}, #{page_length})
|
111
81
|
GENERATED
|
112
82
|
end
|
113
83
|
|
114
84
|
def co_occurrence(element1, element1_namespace, element2, element2_namespace, query)
|
115
85
|
<<-GENERATED
|
116
|
-
declare namespace one = "#{element1_namespace}";
|
117
|
-
declare namespace two = "#{element2_namespace}";
|
118
|
-
import module namespace search = "http://marklogic.com/appservices/search"at "/MarkLogic/appservices/search/search.xqy";
|
119
|
-
let $pairs := cts:element-value-co-occurrences(xs:QName('one:#{element1}'), xs:QName('two:#{element2}'), ('frequency-order', 'fragment-frequency','ordered'), cts:query(search:parse('#{query}')))
|
120
|
-
return
|
121
|
-
for $pair in $pairs
|
122
|
-
return
|
123
|
-
|
86
|
+
declare namespace one = "#{element1_namespace}";
|
87
|
+
declare namespace two = "#{element2_namespace}";
|
88
|
+
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
|
89
|
+
let $pairs := cts:element-value-co-occurrences(xs:QName('one:#{element1}'), xs:QName('two:#{element2}'), ('frequency-order', 'fragment-frequency','ordered'), cts:query(search:parse('#{query}')))
|
90
|
+
return
|
91
|
+
for $pair in $pairs
|
92
|
+
return
|
93
|
+
($pair/cts:value[1]/text(),"|",$pair/cts:value[2]/text(),"|",cts:frequency($pair),"*")
|
124
94
|
GENERATED
|
125
95
|
end
|
96
|
+
private
|
97
|
+
|
98
|
+
def setup_options(options, root, root_namespace)
|
99
|
+
if options then
|
100
|
+
search_options = options
|
101
|
+
else
|
102
|
+
search_options = ActiveDocument::MarkLogicSearchOptions.new
|
103
|
+
end
|
104
|
+
if (search_options.searchable_expression.empty?)
|
105
|
+
search_options.searchable_expression[root_namespace] = root unless root.nil?
|
106
|
+
end
|
107
|
+
return search_options
|
108
|
+
end
|
126
109
|
|
127
110
|
end # end class
|
128
111
|
end # end module
|
@@ -13,26 +13,45 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
# MarkLogicSearchOptions allow you to control exactly how the ActiveDocument::Finder#search method behaves and what additional
|
17
|
-
# information may be returned in the ActiveDocument::SearchResults object
|
18
|
-
# == Attributes
|
19
|
-
# * return_facets - if true then facet information is returned in the resultant ActiveDocument::SearchResults object. Default is true
|
20
|
-
# * value_constraints - this is a #Hash of value constraint names to their options. e.g. search_options_object.value_constraints["Region"] = {"namespace" => "http://wits.nctc.gov", "element" => "Region"}
|
21
16
|
module ActiveDocument
|
17
|
+
# MarkLogicSearchOptions allow you to control exactly how the ActiveDocument::Finder#search method behaves and what additional
|
18
|
+
# information may be returned in the ActiveDocument::SearchResults object
|
19
|
+
# == Attributes
|
20
|
+
# * return_facets - if true then facet information is returned in the resultant ActiveDocument::SearchResults object. Default is true
|
21
|
+
# * value_constraints - Used for creating searches on the value of an element
|
22
|
+
# this is a #Hash of value constraint names to their options.
|
23
|
+
# e.g. search_options_object.value_constraints["Region"] = {"namespace" => "http://wits.nctc.gov", "element" => "Region"}
|
24
|
+
# * word_constraints - Used for creating searches for a word within an element value. This is a #Hash of word constaint names to their options
|
25
|
+
# this is a #Hash of value constraint names to their options.
|
26
|
+
# e.g. search_options_object.word_constraints["Region"] = {"namespace" => "http://wits.nctc.gov", "element" => "Region"}
|
27
|
+
# * range_constraints - Used for searching for a range of values, also for creating facets or doing co-occurents.
|
28
|
+
# This is a #hash of range_constraint names to their options
|
29
|
+
# e.g. search_options_object.range_constraints["Facility Type"] = {"namespace" => "http://wits.nctc.gov", "element" => "FacilityType", "type" => "xs:string", "collation" => "http://marklogic.com/collation/"}
|
30
|
+
# * directory_constraint - Used for specifying that the search should only executed for this directory, to the depth
|
31
|
+
# specified in directory_depth
|
32
|
+
# * searchable_expression - An expression to be searched. Whatever expression is specified is returned from the search.
|
33
|
+
# This is provided as a hash where the key is the element name and the value is the element's namespace. If there is no
|
34
|
+
# namespace then nil or "" should be passed as the value. eg search_options_object.searchable_expression["element"] = "namespace" or
|
35
|
+
# search_options_object.searchable_expression["element"] = "" if there is no namespace for element
|
22
36
|
class MarkLogicSearchOptions
|
23
|
-
attr_accessor :return_facets, :value_constraints, :word_constraints, :range_constraints
|
37
|
+
attr_accessor :return_facets, :value_constraints, :word_constraints, :attribute_constraints, :range_constraints, :directory_constraint, :directory_depth, :searchable_expression
|
24
38
|
|
25
39
|
def initialize
|
26
40
|
@return_facets = true;
|
27
41
|
@value_constraints = Hash.new
|
28
42
|
@word_constraints = Hash.new
|
43
|
+
@attribute_constraints = Hash.new
|
29
44
|
@range_constraints = Hash.new
|
45
|
+
@searchable_expression = Hash.new
|
46
|
+
@directory_depth = 1
|
30
47
|
end
|
31
48
|
|
32
|
-
|
33
49
|
# outputs the object in correctly formatted XML suitable for use in a search
|
34
50
|
def to_s
|
35
51
|
constraints = String.new
|
52
|
+
additional_query = String.new
|
53
|
+
searchable_path = String.new
|
54
|
+
|
36
55
|
@value_constraints.each do |key, value|
|
37
56
|
constraints << <<-XML
|
38
57
|
<constraint name="#{key.gsub(/\s/, '_')}">
|
@@ -53,6 +72,17 @@ module ActiveDocument
|
|
53
72
|
XML
|
54
73
|
end
|
55
74
|
|
75
|
+
@attribute_constraints.each do |constraint_name, attribute_constraint|
|
76
|
+
constraints << <<-XML
|
77
|
+
<constraint name="#{constraint_name.gsub(/\s/, '_')}">
|
78
|
+
<word>
|
79
|
+
<attribute ns="#{attribute_constraint.attribute_namespace unless attribute_constraint.attribute_namespace.nil?}" name="#{attribute_constraint.attribute}"/>
|
80
|
+
<element ns="#{attribute_constraint.element_namespace unless attribute_constraint.element_namespace.nil?}" name="#{attribute_constraint.element}"/>
|
81
|
+
</word>
|
82
|
+
</constraint>
|
83
|
+
XML
|
84
|
+
end
|
85
|
+
|
56
86
|
@range_constraints.each do |key, value|
|
57
87
|
constraints << <<-XML
|
58
88
|
<constraint name="#{key.gsub(/\s/, '_')}">
|
@@ -75,15 +105,35 @@ module ActiveDocument
|
|
75
105
|
constraints << "</range></constraint>"
|
76
106
|
end
|
77
107
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
108
|
+
# serialize the additional query information
|
109
|
+
if @directory_constraint
|
110
|
+
additional_query = "<additional-query>{cts:directory-query(\"#{directory_constraint}\", \"#{directory_depth}\")}</additional-query>"
|
111
|
+
end
|
112
|
+
|
113
|
+
# serialize the searchable_expression
|
114
|
+
if @searchable_expression.size > 0
|
115
|
+
searchable_path << "<searchable-expression"
|
116
|
+
searchable_path << " xmlns:a=\"#{@searchable_expression.keys[0]}\"" unless @searchable_expression.keys[0].nil? or @searchable_expression.keys[0].empty?
|
117
|
+
searchable_path << '>/'
|
118
|
+
searchable_path << "a:" unless @searchable_expression.keys[0].nil? or @searchable_expression.keys[0].empty?
|
119
|
+
searchable_path << "#{@searchable_expression.values[0]}</searchable-expression>"
|
120
|
+
end
|
121
|
+
|
122
|
+
value = "<options xmlns=\"http://marklogic.com/appservices/search\">"
|
123
|
+
unless additional_query.empty?
|
124
|
+
value << additional_query
|
125
|
+
end
|
82
126
|
|
83
127
|
# add in constraints
|
84
128
|
unless constraints.empty?
|
85
129
|
value << constraints
|
86
130
|
end
|
131
|
+
value << "<return-facets>#{@return_facets}</return-facets>"
|
132
|
+
|
133
|
+
# output the searchable expression
|
134
|
+
unless searchable_path.empty?
|
135
|
+
value << searchable_path
|
136
|
+
end
|
87
137
|
# close the options node
|
88
138
|
value << "</options>"
|
89
139
|
|
@@ -108,6 +158,18 @@ module ActiveDocument
|
|
108
158
|
XML
|
109
159
|
end
|
110
160
|
end
|
161
|
+
|
162
|
+
class AttributeConstraint
|
163
|
+
attr_reader :attribute_namespace, :attribute, :element_namespace, :element
|
164
|
+
|
165
|
+
def initialize (attribute_namespace, attribute, element_namespace, element)
|
166
|
+
@attribute_namespace = attribute_namespace
|
167
|
+
@attribute = attribute
|
168
|
+
@element_namespace = element_namespace
|
169
|
+
@element = element
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
111
173
|
end
|
112
174
|
|
113
175
|
end
|
metadata
CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
7
|
+
- 6
|
8
|
+
version: "0.6"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Clark D. Richey, Jr.
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-
|
16
|
+
date: 2010-11-03 00:00:00 -04:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|