activedocument 0.5 → 0.6

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.
@@ -221,7 +221,12 @@ module ActiveDocument
221
221
  else
222
222
  root_namespace = namespace_for_element(root)
223
223
  end
224
- execute_attribute_finder(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace)
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
- execute_finder(element, value, root, element_namespace, root_namespace)
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
- xdmp:document-insert(
30
- "#{uri}",
31
- #{document.to_s},
32
- xdmp:default-permissions(),
33
- xdmp:default-collections())
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, namespace)
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
- <options xmlns="http://marklogic.com/appservices/search">
44
- GENERATED
45
- unless root.nil?
46
- xquery << "<searchable-expression"
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("word:#{value}",
60
- <options xmlns="http://marklogic.com/appservices/search">
51
+ search:search('find_by_element:\"#{value}\"',
61
52
  GENERATED
62
- unless root.nil?
63
- xquery << "<searchable-expression"
64
- xquery << " xmlns:a=\"#{root_namespace}\"" unless root_namespace.nil?
65
- xquery << '>/'
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
- def find_by_attribute(element, attribute, value, root, element_namespace, attribute_namespace, root_namespace)
79
- # todo should the searchable expression portion be refactored?
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("word:#{value}",
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
- unless root.nil?
86
- xquery << "<searchable-expression"
87
- xquery << " xmlns:a=\"#{root_namespace}\"" unless root_namespace.nil?
88
- xquery << '>/'
89
- xquery << "a:" unless root_namespace.nil?
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}',#{option},#{start}, #{page_length})
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
- ($pair/cts:value[1]/text(),"|",$pair/cts:value[2]/text(),"|",cts:frequency($pair),"*")
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
- value = <<-XML
79
- <options xmlns="http://marklogic.com/appservices/search">
80
- <return-facets>#{@return_facets}</return-facets>
81
- XML
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
- - 5
8
- version: "0.5"
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-09-22 00:00:00 -07:00
16
+ date: 2010-11-03 00:00:00 -04:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency