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.
- checksums.yaml +7 -0
- data/lib/azure_search.rb +7 -0
- data/lib/azure_search/errors.rb +26 -0
- data/lib/azure_search/index_batch_operation.rb +59 -0
- data/lib/azure_search/index_field.rb +104 -0
- data/lib/azure_search/index_search_options.rb +177 -0
- data/lib/azure_search/search_index_client.rb +169 -0
- data/lib/azure_search/utils.rb +41 -0
- data/lib/azure_search/version.rb +3 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -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
|
data/lib/azure_search.rb
ADDED
@@ -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
|
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: []
|