riak-client 2.1.0 → 2.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/Guardfile +15 -9
- data/README.markdown +118 -9
- data/lib/riak/bucket.rb +16 -1
- data/lib/riak/bucket_properties.rb +67 -0
- data/lib/riak/bucket_type.rb +48 -0
- data/lib/riak/bucket_typed/bucket.rb +113 -0
- data/lib/riak/client/beefcake/bucket_properties_operator.rb +178 -0
- data/lib/riak/client/beefcake/message_overlay.rb +42 -20
- data/lib/riak/client/beefcake/object_methods.rb +1 -1
- data/lib/riak/client/beefcake/socket.rb +6 -6
- data/lib/riak/client/beefcake_protobuffs_backend.rb +44 -60
- data/lib/riak/client/protobuffs_backend.rb +8 -8
- data/lib/riak/client.rb +7 -2
- data/lib/riak/crdt/base.rb +29 -1
- data/lib/riak/crdt/counter.rb +7 -3
- data/lib/riak/crdt/inner_flag.rb +1 -1
- data/lib/riak/crdt/map.rb +7 -3
- data/lib/riak/crdt/set.rb +7 -4
- data/lib/riak/errors/failed_request.rb +2 -0
- data/lib/riak/errors/search_error.rb +29 -0
- data/lib/riak/locale/en.yml +7 -0
- data/lib/riak/map_reduce.rb +70 -6
- data/lib/riak/robject.rb +19 -3
- data/lib/riak/search/index.rb +73 -0
- data/lib/riak/search/query.rb +133 -0
- data/lib/riak/search/result_collection.rb +91 -0
- data/lib/riak/search/result_document.rb +59 -0
- data/lib/riak/search/schema.rb +65 -0
- data/lib/riak/search.rb +10 -0
- data/lib/riak/secondary_index.rb +6 -0
- data/lib/riak/version.rb +1 -1
- data/spec/fixtures/yz_schema_template.xml +18 -0
- data/spec/integration/riak/bucket_types_spec.rb +218 -39
- data/spec/integration/riak/conflict_resolution_spec.rb +96 -0
- data/spec/integration/riak/crdt_spec.rb +30 -2
- data/spec/integration/riak/properties_spec.rb +69 -0
- data/spec/integration/riak/search_spec.rb +104 -0
- data/spec/integration/riak/secondary_index_spec.rb +18 -0
- data/spec/riak/beefcake_protobuffs_backend/bucket_properties_operator_spec.rb +247 -0
- data/spec/riak/bucket_properties_spec.rb +114 -0
- data/spec/riak/bucket_type_spec.rb +34 -0
- data/spec/riak/bucket_typed/bucket.rb +43 -0
- data/spec/riak/client_spec.rb +16 -8
- data/spec/riak/crdt/counter_spec.rb +2 -1
- data/spec/riak/crdt/map_spec.rb +2 -1
- data/spec/riak/crdt/set_spec.rb +2 -1
- data/spec/riak/map_reduce_spec.rb +169 -124
- data/spec/riak/search/index_spec.rb +62 -0
- data/spec/riak/search/query_spec.rb +88 -0
- data/spec/riak/search/result_collection_spec.rb +87 -0
- data/spec/riak/search/result_document_spec.rb +63 -0
- data/spec/riak/search/schema_spec.rb +63 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/search_config.rb +81 -0
- data/spec/support/test_client.yml +14 -7
- metadata +44 -5
data/lib/riak/robject.rb
CHANGED
@@ -96,6 +96,13 @@ module Riak
|
|
96
96
|
# @see Bucket#get
|
97
97
|
def initialize(bucket, key=nil)
|
98
98
|
@bucket, @key = bucket, key
|
99
|
+
|
100
|
+
# fix a require-loop
|
101
|
+
require 'riak/bucket_typed/bucket'
|
102
|
+
|
103
|
+
if @bucket.is_a? BucketTyped::Bucket
|
104
|
+
@type = @bucket.type.name
|
105
|
+
end
|
99
106
|
@siblings = [ RContent.new(self) ]
|
100
107
|
yield self if block_given?
|
101
108
|
end
|
@@ -128,7 +135,7 @@ module Riak
|
|
128
135
|
raise Conflict, self if conflict?
|
129
136
|
raise ArgumentError, t("content_type_undefined") unless content_type.present?
|
130
137
|
raise ArgumentError, t("zero_length_key") if key == ''
|
131
|
-
@bucket.client.store_object(self, options)
|
138
|
+
@bucket.client.store_object(self, default(options))
|
132
139
|
self
|
133
140
|
end
|
134
141
|
|
@@ -143,7 +150,7 @@ module Riak
|
|
143
150
|
force = options.delete(:force)
|
144
151
|
return self unless @key && (@vclock || force)
|
145
152
|
self.etag = self.last_modified = nil if force
|
146
|
-
bucket.client.reload_object(self, options)
|
153
|
+
bucket.client.reload_object(self, default(options))
|
147
154
|
end
|
148
155
|
|
149
156
|
alias :fetch :reload
|
@@ -154,7 +161,7 @@ module Riak
|
|
154
161
|
def delete(options={})
|
155
162
|
return if key.blank?
|
156
163
|
options[:vclock] = vclock if vclock
|
157
|
-
@bucket.delete(key, options)
|
164
|
+
@bucket.delete(key, default(options))
|
158
165
|
freeze
|
159
166
|
end
|
160
167
|
|
@@ -189,5 +196,14 @@ module Riak
|
|
189
196
|
def to_link(tag)
|
190
197
|
Link.new(@bucket.name, @key, tag)
|
191
198
|
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
def default(options)
|
203
|
+
return options unless options.is_a? Hash
|
204
|
+
return options unless @type
|
205
|
+
|
206
|
+
{type: @type}.merge options
|
207
|
+
end
|
192
208
|
end
|
193
209
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'riak/search'
|
2
|
+
require 'riak/errors/search_error'
|
3
|
+
|
4
|
+
module Riak::Search
|
5
|
+
# A {Riak::Search::Index} is how Solr finds documents in Riak Search 2. A
|
6
|
+
# bucket or bucket type property must be configured to use the index in order
|
7
|
+
# for new and updated documents to be indexed and searchable.
|
8
|
+
class Index
|
9
|
+
# @return [String] the name of the index
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# Initializes an index object, that may or may not exist.
|
13
|
+
#
|
14
|
+
# @param [Riak::Client] client the client connected to the Riak cluster
|
15
|
+
# you wish to operate on
|
16
|
+
# @param [String] name the name of the index
|
17
|
+
def initialize(client, name)
|
18
|
+
@client = client
|
19
|
+
@name = name
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Boolean] does this index exist on Riak?
|
23
|
+
def exists?
|
24
|
+
!!index_data
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Integer] N-value/replication parameter of this index
|
28
|
+
def n_val
|
29
|
+
index_data[:n_val]
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String] schema name of this index
|
33
|
+
def schema
|
34
|
+
index_data[:schema]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Attempt to create this index
|
38
|
+
#
|
39
|
+
# @raise [Riak::SearchError::IndexExistsError] if an index with the given
|
40
|
+
# name already exists
|
41
|
+
def create!(schema = nil, n_val = nil)
|
42
|
+
raise Riak::SearchError::IndexExistsError.new name if exists?
|
43
|
+
|
44
|
+
@client.backend do |b|
|
45
|
+
b.create_search_index name, schema, n_val
|
46
|
+
end
|
47
|
+
|
48
|
+
@index_data = nil
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def index_data
|
55
|
+
return @index_data if defined?(@index_data) && @index_data
|
56
|
+
|
57
|
+
id = nil
|
58
|
+
|
59
|
+
begin
|
60
|
+
id = @client.backend do |b|
|
61
|
+
b.get_search_index name
|
62
|
+
end.index
|
63
|
+
rescue Riak::ProtobuffsFailedRequest => e
|
64
|
+
return nil if e.not_found?
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
|
68
|
+
id = id.first if id.is_a? Array
|
69
|
+
|
70
|
+
return @index_data = id
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'riak/search'
|
2
|
+
|
3
|
+
module Riak::Search
|
4
|
+
# A {Riak::Search::Query} wraps a Solr query for Riak Search 2.
|
5
|
+
class Query
|
6
|
+
|
7
|
+
# @!attribute rows
|
8
|
+
# @return [Numeric] the number of rows to return from the query
|
9
|
+
attr_accessor :rows
|
10
|
+
|
11
|
+
# @!attribute start
|
12
|
+
# @return [Numeric] the offset into the total result set to get results for
|
13
|
+
attr_accessor :start
|
14
|
+
|
15
|
+
# @!attribute sort
|
16
|
+
# @return [String] how Solr should sort the result set
|
17
|
+
attr_accessor :sort
|
18
|
+
|
19
|
+
# @!attribute filter
|
20
|
+
# @return [String] have Solr filter the results prior to returning them
|
21
|
+
attr_accessor :filter
|
22
|
+
|
23
|
+
# @!attribute df
|
24
|
+
# @return [Array<String>] default fields for Solr to search
|
25
|
+
attr_accessor :df
|
26
|
+
|
27
|
+
# @!attribute op
|
28
|
+
# @return [String] Solr search operator
|
29
|
+
attr_accessor :op
|
30
|
+
|
31
|
+
# @!attribute fl
|
32
|
+
# @return [Array<String>] fields for Solr to return
|
33
|
+
attr_accessor :fl
|
34
|
+
|
35
|
+
# @!attribute [r] term
|
36
|
+
# @return [String] the term to query
|
37
|
+
attr_reader :term
|
38
|
+
|
39
|
+
# Initializes a query object.
|
40
|
+
#
|
41
|
+
# @param [Riak::Client] client the client connected to the Riak cluster
|
42
|
+
# @param [String,Riak::Search::Index] index the index to query, either a
|
43
|
+
# {Riak::Search::Index} instance or a {String}
|
44
|
+
# @param [String] term the query term
|
45
|
+
# @param [Hash] options a hash of options to quickly set attributes
|
46
|
+
def initialize(client, index, term, options={ })
|
47
|
+
@client = client
|
48
|
+
validate_index index
|
49
|
+
@term = term
|
50
|
+
@options = options.symbolize_keys
|
51
|
+
|
52
|
+
set_defaults
|
53
|
+
consume_options
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get results from the query. Performs the query when called the first time.
|
57
|
+
#
|
58
|
+
# @return [Riak::Search::ResultCollection] collection of results
|
59
|
+
def results
|
60
|
+
return @results if defined? @results
|
61
|
+
|
62
|
+
@results = ResultCollection.new @client, raw_results
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def index_name
|
68
|
+
return @index if @index.is_a? String
|
69
|
+
return @index.name
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_index(index)
|
73
|
+
if index.is_a? String
|
74
|
+
index = Riak::Search::Index.new @client, index
|
75
|
+
end
|
76
|
+
|
77
|
+
unless index.is_a? Riak::Search::Index
|
78
|
+
raise Riak::SearchError::IndexArgumentError.new index
|
79
|
+
end
|
80
|
+
|
81
|
+
unless index.exists?
|
82
|
+
raise Riak::SearchError::IndexNonExistError.new index.name
|
83
|
+
end
|
84
|
+
|
85
|
+
@index = index
|
86
|
+
end
|
87
|
+
|
88
|
+
def set_defaults
|
89
|
+
@rows = nil
|
90
|
+
@start = nil
|
91
|
+
|
92
|
+
@sort = nil
|
93
|
+
@filter = nil
|
94
|
+
|
95
|
+
@df = %w{text}
|
96
|
+
@op = nil
|
97
|
+
@fl = %w{_yz_rb _yz_rk _yz_rt score}
|
98
|
+
|
99
|
+
@presort = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def consume_options
|
103
|
+
@rows = @options[:rows] if @options[:rows]
|
104
|
+
@start = @options[:start] if @options[:start]
|
105
|
+
|
106
|
+
@sort = @options[:sort] if @options[:sort]
|
107
|
+
@filter = @options[:filter] if @options[:filter]
|
108
|
+
|
109
|
+
@df = @options[:df] if @options[:df]
|
110
|
+
@op = @options[:op] if @options[:op]
|
111
|
+
@fl = @options[:fl] if @options[:fl]
|
112
|
+
end
|
113
|
+
|
114
|
+
def prepare_options
|
115
|
+
configured_options = {
|
116
|
+
rows: @rows,
|
117
|
+
start: @start,
|
118
|
+
sort: @sort,
|
119
|
+
filter: @filter,
|
120
|
+
df: @df.join(' '),
|
121
|
+
op: @op,
|
122
|
+
fl: @fl
|
123
|
+
}
|
124
|
+
@options.merge configured_options
|
125
|
+
end
|
126
|
+
|
127
|
+
def raw_results
|
128
|
+
@client.backend do |be|
|
129
|
+
be.search index_name, @term, prepare_options
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'riak/search'
|
2
|
+
|
3
|
+
module Riak::Search
|
4
|
+
|
5
|
+
# A collection of Riak Search 2 ("Yokozuna") results. Provides direct access
|
6
|
+
# to the {Riak::RObject} instances found, and access through the #docs method
|
7
|
+
# to the results as returned by Solr.
|
8
|
+
class ResultCollection
|
9
|
+
# @return [Riak::Client]
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
# @return [Hash] the de-serialzed hash returned from Solr
|
13
|
+
attr_reader :raw
|
14
|
+
|
15
|
+
# @return [Numeric] the maximum score found by Solr
|
16
|
+
attr_reader :max_score
|
17
|
+
|
18
|
+
# @return [Integer] the number of documents in this collection
|
19
|
+
attr_reader :length
|
20
|
+
|
21
|
+
# @return [Integer] the total number of documents matched, including ones
|
22
|
+
# not returned due to row-limiting
|
23
|
+
attr_reader :num_found
|
24
|
+
|
25
|
+
# Initialize a {ResultCollection} with the client queried and the raw
|
26
|
+
# JSON returned from the search API.
|
27
|
+
#
|
28
|
+
# This is automatically called by {Riak::Search::Query}#results
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def initialize(client, raw_results)
|
32
|
+
@client = client
|
33
|
+
@raw = raw_results
|
34
|
+
@max_score = raw['max_score']
|
35
|
+
@num_found = raw['num_found']
|
36
|
+
@length = raw['docs'].length
|
37
|
+
end
|
38
|
+
|
39
|
+
# Access the individual documents from the search results. The document
|
40
|
+
# metadata are each wrapped in a {Riak::Search::ResultDocument}.
|
41
|
+
#
|
42
|
+
# @return [Array<Riak::Search::ResultDocument>] individual documents
|
43
|
+
def docs
|
44
|
+
@docs ||= raw['docs'].map do |result|
|
45
|
+
ResultDocument.new client, result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Boolean] does this collection contain any documents?
|
50
|
+
def empty?
|
51
|
+
length == 0
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param [Integer] index the index of the [Riak::RObject] to load and return
|
55
|
+
# @return [Riak::RObject,NilClass] the found object, or nil if the index
|
56
|
+
# is out of range
|
57
|
+
def [](index)
|
58
|
+
doc = docs[index]
|
59
|
+
return nil if doc.nil?
|
60
|
+
|
61
|
+
doc.robject
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Riak::RObject,NilClass] the first found object, or nil if the
|
65
|
+
# index is out of range
|
66
|
+
def first
|
67
|
+
self[0]
|
68
|
+
end
|
69
|
+
|
70
|
+
# {Enumerable}-compatible iterator method. If a block is given, yields with
|
71
|
+
# each {Riak::RObject} in the collection. If no block is given, returns an
|
72
|
+
# {Enumerator} over each {Riak::RObject in the collection.
|
73
|
+
# @yieldparam robject [Riak::RObject]
|
74
|
+
# @return [Enumerator<Riak::RObject>]
|
75
|
+
def each_robject
|
76
|
+
enum = docs.each_with_index
|
77
|
+
|
78
|
+
if block_given?
|
79
|
+
enum.each do |doc, idx|
|
80
|
+
yield self[idx]
|
81
|
+
end
|
82
|
+
else
|
83
|
+
Enumerator.new do |yielder|
|
84
|
+
enum.each do |doc, idx|
|
85
|
+
yielder << self[idx]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Riak::Search
|
2
|
+
|
3
|
+
# A single document from a Riak Search 2 response. Materializes the document
|
4
|
+
# fields into {Riak::BucketType}, {Riak::Bucket}, and {Riak::RObject}
|
5
|
+
# instances on demand.
|
6
|
+
class ResultDocument
|
7
|
+
# @return [Riak::Client]
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
# @return [Hash] the de-serialized hash returned from Solr
|
11
|
+
attr_reader :raw
|
12
|
+
|
13
|
+
# Iniitalize a {ResultDocument} with the client queried and the relevant
|
14
|
+
# part of the JSON returned from the search API.
|
15
|
+
#
|
16
|
+
# This is automatically called by {Riak::Search::ResultCollection}#docs
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def initialize(client, raw)
|
20
|
+
@client = client
|
21
|
+
@raw = raw
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String] the key of the result
|
25
|
+
def key
|
26
|
+
@key ||= raw['_yz_rk']
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Riak::BucketType] the bucket type containing the result
|
30
|
+
def bucket_type
|
31
|
+
@bucket_type ||= client.bucket_type raw['_yz_rt']
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Riak::Bucket] the bucket containing the result
|
35
|
+
def bucket
|
36
|
+
@bucket ||= bucket_type.bucket raw['_yz_rb']
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Numeric] the score of the match
|
40
|
+
def score
|
41
|
+
@score ||= Float(raw['score'])
|
42
|
+
end
|
43
|
+
|
44
|
+
# Provides access to other parts of the result document without
|
45
|
+
# materializing them. Useful when querying non-default fields.
|
46
|
+
#
|
47
|
+
# @return [String,Numeric] other search result document field
|
48
|
+
def [](field_name)
|
49
|
+
raw[field_name.to_s]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Loads the {Riak::RObject} referred to by the result document.
|
53
|
+
#
|
54
|
+
# @return [Riak::RObject]
|
55
|
+
def robject
|
56
|
+
@robject ||= bucket.get key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'riak/search'
|
2
|
+
require 'riak/errors/search_error'
|
3
|
+
|
4
|
+
module Riak::Search
|
5
|
+
# A schema is a Riak Search 2 concept that describes how to index documents.
|
6
|
+
# They're implemented as a standard Solr XML schema.
|
7
|
+
class Schema
|
8
|
+
# @return [String] the name of the schema
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Initializes a schema object, that may or may not exist.
|
12
|
+
#
|
13
|
+
# @param [Riak::Client] client the client connected to the Riak cluster
|
14
|
+
# you wish to operate on
|
15
|
+
# @param [String] name the name of the schema
|
16
|
+
def initialize(client, name)
|
17
|
+
@client = client
|
18
|
+
@name = name
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Boolean] does this schema exist on Riak?
|
22
|
+
def exists?
|
23
|
+
!!schema_data
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [String] the XML content of this schema
|
27
|
+
def content
|
28
|
+
schema_data.content
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [String] content the XML content of this schema
|
32
|
+
# @raise [Riak::SearchError::SchemaExistsError] if a schema with the given
|
33
|
+
# name already exists
|
34
|
+
def create!(content)
|
35
|
+
raise Riak::SearchError::SchemaExistsError.new name if exists?
|
36
|
+
|
37
|
+
@client.backend do |b|
|
38
|
+
b.create_search_schema name, content
|
39
|
+
end
|
40
|
+
|
41
|
+
@schema_data = nil
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def schema_data
|
48
|
+
return @schema_data if defined?(@schema_data) && @schema_data
|
49
|
+
|
50
|
+
sd = nil
|
51
|
+
|
52
|
+
begin
|
53
|
+
sd = @client.backend do |b|
|
54
|
+
b.get_search_schema name
|
55
|
+
end
|
56
|
+
rescue Riak::ProtobuffsFailedRequest => e
|
57
|
+
return nil if e.not_found?
|
58
|
+
raise e
|
59
|
+
end
|
60
|
+
|
61
|
+
return @schema_data = sd
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
data/lib/riak/search.rb
ADDED
data/lib/riak/secondary_index.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'riak/index_collection'
|
2
|
+
require 'riak/bucket_typed/bucket'
|
3
|
+
|
2
4
|
module Riak
|
3
5
|
class SecondaryIndex
|
4
6
|
include Util::Translation
|
@@ -16,6 +18,10 @@ module Riak
|
|
16
18
|
@query = query
|
17
19
|
@options = options
|
18
20
|
|
21
|
+
if @bucket.is_a? Riak::BucketTyped::Bucket
|
22
|
+
@options = { type: @bucket.type.name }.merge @options
|
23
|
+
end
|
24
|
+
|
19
25
|
validate_options
|
20
26
|
end
|
21
27
|
|
data/lib/riak/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<schema name="SCHEMA_NAME" version="1.5">
|
3
|
+
<fields>
|
4
|
+
<field name="_yz_id" type="_yz_str" indexed="true" stored="true" multiValued="false" required="true" />
|
5
|
+
<field name="_yz_ed" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
6
|
+
<field name="_yz_pn" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
7
|
+
<field name="_yz_fpn" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
8
|
+
<field name="_yz_vtag" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
9
|
+
<field name="_yz_rk" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
10
|
+
<field name="_yz_rb" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
11
|
+
<field name="_yz_rt" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
12
|
+
<field name="_yz_err" type="_yz_str" indexed="true" stored="true" multiValued="false"/>
|
13
|
+
</fields>
|
14
|
+
<uniqueKey>_yz_id</uniqueKey>
|
15
|
+
<types>
|
16
|
+
<fieldType name="_yz_str" class="solr.StrField" sortMissingLast="true" />
|
17
|
+
</types>
|
18
|
+
</schema>
|