azure_search 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bc148b6807b2928ac0842c5f0839cad1375fa433
4
+ data.tar.gz: b696a4ceb1c8a277e5bd9639b8fc326ffbfd32cf
5
+ SHA512:
6
+ metadata.gz: 7f8441c96cae85be15a736906bb1a31c489e201fb20318bdb09107369494ef9bf55d9f23fc657ee97e083b79f5cd921cf5a049fa92c5dbdb4656d2d8b8623a52
7
+ data.tar.gz: 03f9bfa8c10d7c189620dc21928c995613426f89f6d126d757e27d94c61b7efdeb77b4502e4e13d58786b6be94ca9b5361414bc4d452a0ffbe6535eb845a8942
@@ -0,0 +1,7 @@
1
+ require 'azure_search/utils'
2
+ require 'azure_search/errors'
3
+ require 'azure_search/version'
4
+ require 'azure_search/index_field'
5
+ require 'azure_search/search_index_client'
6
+ require 'azure_search/index_search_options'
7
+ require 'azure_search/index_batch_operation'
@@ -0,0 +1,26 @@
1
+ module AzureSearch
2
+
3
+ # Defines errors that are raised by AzureSearch client.
4
+ #
5
+ # @since 0.1.0
6
+ module Errors
7
+
8
+ # Raised to indicate that a HTTP request needs to be retried.
9
+ class RetriableHttpError < StandardError
10
+ # @return [Symbol] The response status code.
11
+ attr_accessor :code
12
+ # @return [Symbol] The error message.
13
+ attr_accessor :message
14
+
15
+ def initialize(code, message)
16
+ self.code = code
17
+ self.message = message
18
+ end
19
+
20
+ def to_s
21
+ "RetriableHttpError <#{self.code}>: #{self.message}"
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,59 @@
1
+ require 'json'
2
+
3
+ module AzureSearch
4
+
5
+ # Represents a batch operation in an indexing request.
6
+ class IndexBatchOperation
7
+ # Encapsulates the supplied document in an IndexUploadOperation.
8
+ #
9
+ # @param [Hash] document The document.
10
+ # @return [Hash] The upload operation as a Hash.
11
+ def self.upload(document)
12
+ IndexUploadOperation.new(document).to_hash
13
+ end
14
+
15
+ # Encapsulates a delete request in an IndexDeleteOperation.
16
+ #
17
+ # @param [String] key_name The key name.
18
+ # @param [String] key_value The key value.
19
+ def self.delete(key_name, key_value)
20
+ IndexDeleteOperation.new(key_name, key_value).to_hash
21
+ end
22
+
23
+ # @todo Add support for merge & merge_or_upload
24
+ end
25
+
26
+ # Represents an upload operation of a document.
27
+ class IndexUploadOperation < IndexBatchOperation
28
+ def initialize(document)
29
+ @document = document
30
+ end
31
+
32
+ # Returns the upload operation as a Hash.
33
+ #
34
+ # @return [Hash] The upload operation.
35
+ def to_hash
36
+ @document["@search.action"] = "upload"
37
+ @document
38
+ end
39
+ end
40
+
41
+ # Represents a document deletion request.
42
+ class IndexDeleteOperation < IndexBatchOperation
43
+ def initialize(key_name, key_value)
44
+ @key_name = key_name
45
+ @key_value = key_value
46
+ end
47
+
48
+ # Returns the delete operation as a Hash.
49
+ #
50
+ # @return [Hash] The delete operation.
51
+ def to_hash
52
+ {
53
+ @key_name => @key_value,
54
+ "@search_action" => "delete"
55
+ }
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,104 @@
1
+ module AzureSearch
2
+
3
+ # Represents an Index field definition.
4
+ class IndexField
5
+ # Valid EDM (Entity Data Model) data types.
6
+ VALID_EDM_TYPES = [
7
+ "Edm.String",
8
+ "Collection(Edm.String)",
9
+ "Edm.Boolean",
10
+ "Edm.Int32",
11
+ "Edm.Int64",
12
+ "Edm.Double",
13
+ "Edm.DateTimeOffset",
14
+ "Edm.GeographyPoint"
15
+ ].freeze
16
+
17
+ def initialize(name, type)
18
+ raise "Field name is required." unless !name.empty?
19
+ @name = name
20
+ raise "Invalid field type." unless VALID_EDM_TYPES.include? type
21
+ @type = type
22
+ end
23
+
24
+ # Sets the analyzer name used for search and indexing.
25
+ #
26
+ # @param [String] analyzer The analyzer name.
27
+ # @return [self] The current instance.
28
+ def analyzer(analyzer)
29
+ @analyzer = analyzer
30
+ self
31
+ end
32
+
33
+ # Sets the field to be searchable.
34
+ #
35
+ # @param [TrueClass,FalseClass] searchable true or false.
36
+ # @return [self] The current instance.
37
+ def searchable(searchable)
38
+ raise "searchable must be a boolean." unless is_bool? searchable
39
+ @searchable = searchable
40
+ self
41
+ end
42
+
43
+ # Sets the field to be filterable.
44
+ #
45
+ # @param [TrueClass,FalseClass] filterable true or false.
46
+ # @return [self] The current instance.
47
+ def filterable(filterable)
48
+ raise "filterable must be a boolean." unless is_bool? filterable
49
+ @filterable = filterable
50
+ self
51
+ end
52
+
53
+ # Sets the field to be retrievable.
54
+ #
55
+ # @param [TrueClass,FalseClass] retrievable true or false.
56
+ # @return [self] The current instance.
57
+ def retrievable(retrievable)
58
+ raise "retrievable must be a boolean." unless is_bool? retrievable
59
+ @retrievable = retrievable
60
+ self
61
+ end
62
+
63
+ # Sets the field to be sortable.
64
+ #
65
+ # @param [TrueClass,FalseClass] sortable true or false.
66
+ # @return [self] The current instance.
67
+ def sortable(sortable)
68
+ raise "sortable must be a boolean." unless is_bool? sortable
69
+ @sortable = sortable
70
+ self
71
+ end
72
+
73
+ # Sets the field to be facetable.
74
+ #
75
+ # @param [TrueClass,FalseClass] facetable true or false.
76
+ # @return [self] The current instance.
77
+ def facetable(facetable)
78
+ raise "facetable must be a boolean." unless is_bool? facetable
79
+ @facetable = facetable
80
+ self
81
+ end
82
+
83
+ # Sets the field to be the key (Only Edm.String fields can be keys).
84
+ #
85
+ # @param [TrueClass,FalseClass] key true or false.
86
+ # @return [self] The current instance.
87
+ def key(key)
88
+ raise "key must be a boolean." unless is_bool? key
89
+ raise "Only Edm.String fields can be keys." unless @type == "Edm.String"
90
+ @key = key
91
+ self
92
+ end
93
+
94
+ # Converts this IndexField to a Hash.
95
+ #
96
+ # @return [Hash] Hash representation of IndexField.
97
+ def to_hash
98
+ hash = {}
99
+ instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var) }
100
+ hash
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,177 @@
1
+ require 'azure_search/utils'
2
+
3
+ module AzureSearch
4
+
5
+ # Represents search options that will be sent along with a search request.
6
+ class IndexSearchOptions
7
+ SPECIAL_PARAMS = %w(count filter orderby select top skip).freeze
8
+
9
+ # Specifies whether to fetch the total count of results.
10
+ #
11
+ # @param [TrueClass,FalseClass] val true or false.
12
+ # @return [self] the current instance.
13
+ def include_count(val)
14
+ raise "include_count requires a boolean value." unless is_bool?(val)
15
+ @count = val
16
+ self
17
+ end
18
+
19
+ # Sets the structured search expression in standard OData syntax.
20
+ #
21
+ # @param [String] val The filter expression.
22
+ # @return [self] The current instance.
23
+ def filter(val)
24
+ raise "filter requires a String." unless val.is_a? String
25
+ @filter = val
26
+ self
27
+ end
28
+
29
+ # Sets the list of comma-separated expressions to sort the results by.
30
+ #
31
+ # @param [String] val Comma-separated expressions.
32
+ # @return [self] The current instance.
33
+ def order_by(val)
34
+ raise "order_by requires a String." unless val.is_a? String
35
+ @orderby = val
36
+ self
37
+ end
38
+
39
+ # Sets the list of comma-separated fields to retrieve.
40
+ #
41
+ # @param [String] val Comma-separated fields.
42
+ # @return [self] The current instance.
43
+ def select(val)
44
+ raise "select requires a String." unless val.is_a? String
45
+ @select = val
46
+ self
47
+ end
48
+
49
+ # Sets the list of comma-separated field names to search for the specified text.
50
+ #
51
+ # @param [String] val Comma-separated field names.
52
+ # @return [self] The current instance.
53
+ def search_fields(val)
54
+ raise "search_fields requires a String." unless val.is_a? String
55
+ @searchFields = val
56
+ self
57
+ end
58
+
59
+ # Sets the list of fields to facet by.
60
+ #
61
+ # @param [Array] fs The list of fields.
62
+ # @return [self] The current instance.
63
+ def facets(fs)
64
+ raise "facts requires an Array of Strings." unless fs.is_a? Array
65
+ @facet = fs
66
+ self
67
+ end
68
+
69
+ # Sets the set of comma-separated field names used for hit highlights.
70
+ #
71
+ # @param [String] hl Comma-separated field names.
72
+ # @return [self] The current instance.
73
+ def highlight(hl)
74
+ raise "highlight requires a String." unless hl.is_a? String
75
+ @highlight = hl
76
+ self
77
+ end
78
+
79
+ # Sets the string tag that appends to hit highlights (defaults to <em>).
80
+ #
81
+ # @param [String] hpt The string tag.
82
+ # @return [self] The current instance.
83
+ def highlight_pre_tag(hpt)
84
+ raise "highlight_pre_tag requires an HTML string." unless has_html?(hpt)
85
+ @highlightPreTag = hpt
86
+ self
87
+ end
88
+
89
+ # Sets the string tag that appends to hit highlights (defaults to </em>).
90
+ #
91
+ # @param [String] hpt The string tag.
92
+ # @return [self] The current instance.
93
+ def highlight_post_tag(hpt)
94
+ raise "highlight_post_tag requires an HTML string." unless has_html?(hpt)
95
+ @highlightPostTag = hpt
96
+ self
97
+ end
98
+
99
+ # Sets the name of a scoring profile to evaluate match scores for matching documents.
100
+ #
101
+ # @param [String] sp The scoring profile name.
102
+ # @return [self] The current instance.
103
+ def scoring_profile(sp)
104
+ raise "scoring_profile requires a String." unless sp.is_a? String
105
+ @scoringProfile = sp
106
+ self
107
+ end
108
+
109
+ # Sets the values for each parameter defined in a scoring function.
110
+ #
111
+ # @param [Array] params The parameters values.
112
+ # @return [self] The current instance.
113
+ def scoring_parameters(params)
114
+ raise "scoring_parameters requires an Array of Strings." unless params.is_a? Array
115
+ @scoringParameter = params
116
+ self
117
+ end
118
+
119
+ # Sets the number of search results to retrieve (defaults to 50).
120
+ #
121
+ # @param [Integer] val The number of search results.
122
+ # @return [self] The current instance.
123
+ def top(val)
124
+ raise "top requires an Integer." unless val.is_a? Integer
125
+ @top = val
126
+ self
127
+ end
128
+
129
+ # Sets the number of search results to skip.
130
+ #
131
+ # @param [Integer] val The number to skip (cannot be greater than 100,000).
132
+ # @return [self] The current instance.
133
+ def skip(val)
134
+ raise "skip requires an Integer." unless val.is_a? Integer
135
+ @skip = val
136
+ self
137
+ end
138
+
139
+ # Specifies whether any or all of the search terms must be matched.
140
+ #
141
+ # @param [String] mode The search mode.
142
+ # @return [self] The current instance.
143
+ def search_mode(mode)
144
+ raise "invalid search mode." unless ["any", "all"].include? mode
145
+ @searchMode = mode
146
+ self
147
+ end
148
+
149
+ # Sets the percentage of the index that must be covered by a search query.
150
+ #
151
+ # @param [Float] val The percentage (must be between 0 and 100).
152
+ # @return [self] The current instance.
153
+ def minimum_coverage(val)
154
+ raise "minimum_coverage requires a Float." unless val.is_a? Float
155
+ raise "minimum_coverage must be between 0 and 100" unless val.between?(0, 100)
156
+ @minimumCoverage = val
157
+ self
158
+ end
159
+
160
+ # Returns the search options as a Hash.
161
+ #
162
+ # @return [Hash] The search options as a Hash.
163
+ def to_hash
164
+ hash = {}
165
+ instance_variables.each {|var|
166
+ varname = var.to_s.delete("@")
167
+ if SPECIAL_PARAMS.include? varname
168
+ hash["$"+varname] = instance_variable_get(var)
169
+ else
170
+ hash[varname] = instance_variable_get(var)
171
+ end
172
+ }
173
+ hash
174
+ end
175
+ end
176
+
177
+ end
@@ -0,0 +1,169 @@
1
+ require 'azure_search/index_search_options'
2
+ require 'azure_search/errors'
3
+ require 'azure_search/utils'
4
+ require 'http'
5
+
6
+ # Core module common across the entire API.
7
+ #
8
+ # @author Faissal Elamraoui
9
+ # @since 0.1.0
10
+ module AzureSearch
11
+ API_VERSION = "2016-09-01".freeze
12
+
13
+ # Client to perform requests to an Azure Search service.
14
+ class SearchIndexClient
15
+ include AzureSearch::Errors
16
+
17
+ # @return [Symbol] The search service name.
18
+ attr_accessor :service_name
19
+ # @return [Symbol] The index name.
20
+ attr_accessor :index_name
21
+ # @return [Symbol] The API key generated for the provisioned Search service.
22
+ attr_accessor :api_key
23
+
24
+ def initialize(service_name, index_name, api_key)
25
+ if service_name.empty? || index_name.empty? || api_key.empty?
26
+ raise StandardError, "Must provide service_name, index_name and api_key when creating client."
27
+ end
28
+
29
+ self.service_name = service_name
30
+ self.index_name = index_name
31
+ self.api_key = api_key
32
+ end
33
+
34
+ # Checks if the specified index exists.
35
+ #
36
+ # @return [TrueClass,FalseClass] true if the index exists, false otherwise.
37
+ def exists
38
+ resp = create_request().get(build_index_definition_url())
39
+ if resp.code == 404
40
+ return false
41
+ end
42
+ raise_on_http_error(resp)
43
+ return true
44
+ end
45
+
46
+ # Creates the index based on the provided index definition.
47
+ #
48
+ # @param [Hash] definition The index definition.
49
+ # @option definition [String] :name The index name.
50
+ # @option definition [Array<IndexField>] :fields Array of fields.
51
+ # @option definition [Array] :suggesters Array of suggesters.
52
+ def create(definition)
53
+ raise "Index definition must be a Hash." unless definition.is_a? Hash
54
+ definition[:name] = self.index_name unless !definition[:name]
55
+ resp = create_request().post(build_index_list_url(), :json => definition)
56
+ raise_on_http_error(resp)
57
+ return JSON.parse(resp.to_s)
58
+ end
59
+
60
+ # Creates or updates the index based on the provided index definition.
61
+ #
62
+ # @param [Hash] definition The index definition.
63
+ # @option definition [String] :name The index name.
64
+ # @option definition [Array<IndexField>] :fields Array of fields.
65
+ # @option definition [Array] :suggesters Array of suggesters.
66
+ def create_or_update(definition)
67
+ raise "Index definition must be a Hash." unless definition.is_a? Hash
68
+ definition[:name] = self.index_name unless definition[:name]
69
+ resp = create_request().put(build_index_definition_url(), :json => definition)
70
+ raise_on_http_error(resp)
71
+ return resp.to_s.empty? ? nil : JSON.parse(resp.to_s)
72
+ end
73
+
74
+ # Deletes the specified index.
75
+ #
76
+ # @return [TrueClass,FalseClass] true if the index is deleted, false otherwise.
77
+ def delete
78
+ resp = create_request().delete(build_index_definition_url())
79
+ if resp.code == 404
80
+ return false
81
+ end
82
+ raise_on_http_error(resp)
83
+ return true
84
+ end
85
+
86
+ # Inserts documents in batch.
87
+ #
88
+ # @param [Array<IndexBatchOperation>] operations Array of upload operations.
89
+ # @param [Integer] chunk_size The batch size. Must not exceed 1000 documents.
90
+ def batch_insert(operations, chunk_size=1000)
91
+ raise "Batch request must not exceed 1000 documents." unless chunk_size <= 1000
92
+ operations.each_slice(chunk_size)
93
+ .to_a
94
+ .each{|op|
95
+ resp = create_request().post(build_indexing_url(), :json => {:value => op})
96
+ raise_on_http_error(resp)
97
+ resp.to_s
98
+ }
99
+ end
100
+
101
+ # Search the index for the supplied text.
102
+ #
103
+ # @param [String] text The text to search for.
104
+ # @param [IndexSearchOptions] options Options to configure the search request.
105
+ #
106
+ # @return [Hash] Parsed JSON response.
107
+ def search(text, options)
108
+ resp = create_request().get(build_index_search_url(text, options))
109
+ raise_on_http_error(resp)
110
+ return JSON.parse(resp.to_s)
111
+ end
112
+
113
+ # Lookup an indexed document by key.
114
+ #
115
+ # @param [String] key The key.
116
+ # @return [Hash] The document identified by the supplied key.
117
+ def lookup(key)
118
+ resp = create_request().get(build_index_lookup_url(key))
119
+ raise_on_http_error(resp)
120
+ doc = JSON.parse(resp.to_s)
121
+ doc.delete("@odata.context")
122
+ return doc
123
+ end
124
+
125
+ private
126
+ def build_index_definition_url
127
+ "https://#{self.service_name}.search.windows.net/indexes/#{self.index_name}?api-version=#{API_VERSION}"
128
+ end
129
+
130
+ def build_index_list_url
131
+ "https://#{self.service_name}.search.windows.net/indexes?api-version=#{API_VERSION}"
132
+ end
133
+
134
+ def build_indexing_url
135
+ "https://#{self.service_name}.search.windows.net/indexes/#{self.index_name}/docs/index?api-version=#{API_VERSION}"
136
+ end
137
+
138
+ def build_index_search_url(text, options)
139
+ query = {"search" => URI.encode_www_form_component(text)}.merge(options.to_hash)
140
+ "https://#{self.service_name}.search.windows.net/indexes/#{self.index_name}/docs?api-version=#{API_VERSION}&" << to_query_string(query)
141
+ end
142
+
143
+ def build_index_lookup_url(key)
144
+ "https://#{self.service_name}.search.windows.net/indexes/#{self.index_name}/docs('#{key}')?api-version=#{API_VERSION}"
145
+ end
146
+
147
+ def create_request
148
+ HTTP.headers({
149
+ "Content-Type" => "application/json",
150
+ "api-key" => self.api_key
151
+ })
152
+ end
153
+
154
+ def raise_on_http_error(response)
155
+ status_code = response.code
156
+ if status_code > 399
157
+ # 503 means the server is asking for backoff + retry
158
+ if status_code == 503
159
+ raise RetriableHttpError.new(status_code, response.to_s)
160
+ else
161
+ raise StandardError, "#{response.to_s}"
162
+ end
163
+ end
164
+ end
165
+
166
+ def validate_search_option(options)
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,41 @@
1
+ require 'nokogiri'
2
+
3
+ module AzureSearch
4
+
5
+ # Checks if the supplied value is a Boolean.
6
+ #
7
+ # @param [Object] value The value to check.
8
+ # @return [TrueClass,FalseClass] true or false.
9
+ def is_bool?(value); [true, false].include? value end
10
+
11
+ # Checks if the supplied text contains valid HTML.
12
+ #
13
+ # @param [String] text The text to check.
14
+ # @return [TrueClass,FalseClass] true or false.
15
+ def has_html?(text); Nokogiri::XML(text).errors.empty? end
16
+
17
+ # Converts a Hash into query parameters string.
18
+ #
19
+ # @param [Hash] params The hash to convert.
20
+ # @return [String] query string.
21
+ def to_query_string(params)
22
+ params.map{|k,v|
23
+ if v.nil?
24
+ k.to_s
25
+ elsif v.respond_to?(:to_ary)
26
+ v.to_ary.map{|w|
27
+ str = k.to_s.dup
28
+ unless w.nil?
29
+ str << '='
30
+ str << w.to_s
31
+ end
32
+ }.join('&')
33
+ else
34
+ str = k.to_s.dup
35
+ str << '='
36
+ str << v.to_s
37
+ end
38
+ }.join('&')
39
+ end
40
+
41
+ end
@@ -0,0 +1,3 @@
1
+ module AzureSearch
2
+ VERSION = "0.1.0".freeze
3
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: azure_search
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Faissal Elamraoui
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: http
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.15'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.15'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '12.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '12.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.6'
83
+ description: This library allows you to interact with Microsoft Azure Search using
84
+ Ruby.
85
+ email:
86
+ - amr.faissal@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - lib/azure_search.rb
92
+ - lib/azure_search/errors.rb
93
+ - lib/azure_search/index_batch_operation.rb
94
+ - lib/azure_search/index_field.rb
95
+ - lib/azure_search/index_search_options.rb
96
+ - lib/azure_search/search_index_client.rb
97
+ - lib/azure_search/utils.rb
98
+ - lib/azure_search/version.rb
99
+ homepage: https://github.com/amrfaissal/azuresearch-ruby-client.git
100
+ licenses:
101
+ - MIT
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.6.11
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Microsoft Azure Search Client Library for Ruby.
123
+ test_files: []