2222import org .apache .lucene .document .Field ;
2323import org .apache .lucene .index .IndexOptions ;
2424import org .apache .lucene .index .IndexableField ;
25+ import org .apache .lucene .index .LeafReaderContext ;
2526import org .apache .lucene .search .Query ;
27+ import org .apache .lucene .search .SortField ;
2628import org .apache .lucene .search .TermInSetQuery ;
27- import org .elasticsearch .common .Nullable ;
29+ import org .apache .lucene .util .BytesRef ;
30+ import org .elasticsearch .Version ;
31+ import org .elasticsearch .common .lucene .BytesRefs ;
2832import org .elasticsearch .common .lucene .Lucene ;
2933import org .elasticsearch .common .xcontent .XContentBuilder ;
34+ import org .elasticsearch .index .Index ;
3035import org .elasticsearch .index .IndexSettings ;
36+ import org .elasticsearch .index .fielddata .AtomicFieldData ;
3137import org .elasticsearch .index .fielddata .IndexFieldData ;
38+ import org .elasticsearch .index .fielddata .IndexFieldData .XFieldComparatorSource .Nested ;
39+ import org .elasticsearch .index .fielddata .fieldcomparator .BytesRefFieldComparatorSource ;
40+ import org .elasticsearch .index .fielddata .IndexFieldDataCache ;
41+ import org .elasticsearch .index .fielddata .ScriptDocValues ;
42+ import org .elasticsearch .index .fielddata .SortedBinaryDocValues ;
3243import org .elasticsearch .index .fielddata .plain .PagedBytesIndexFieldData ;
3344import org .elasticsearch .index .query .QueryShardContext ;
45+ import org .elasticsearch .indices .breaker .CircuitBreakerService ;
46+ import org .elasticsearch .search .MultiValueMode ;
3447
3548import java .io .IOException ;
3649import java .util .Arrays ;
@@ -109,15 +122,31 @@ public boolean isSearchable() {
109122 }
110123
111124 @ Override
112- public Query termQuery (Object value , @ Nullable QueryShardContext context ) {
125+ public Query termQuery (Object value , QueryShardContext context ) {
113126 return termsQuery (Arrays .asList (value ), context );
114127 }
115128
116129 @ Override
117- public Query termsQuery (List <?> values , @ Nullable QueryShardContext context ) {
130+ public Query termsQuery (List <?> values , QueryShardContext context ) {
118131 if (indexOptions () != IndexOptions .NONE ) {
119- // 6.x index, _id is indexed
120- return super .termsQuery (values , context );
132+ failIfNotIndexed ();
133+ BytesRef [] bytesRefs = new BytesRef [values .size ()];
134+ final boolean is5xIndex = context .indexVersionCreated ().before (Version .V_6_0_0_alpha3 );
135+ for (int i = 0 ; i < bytesRefs .length ; i ++) {
136+ BytesRef id ;
137+ if (is5xIndex ) {
138+ // 5.x index with index.mapping.single_type = true
139+ id = BytesRefs .toBytesRef (values .get (i ));
140+ } else {
141+ Object idObject = values .get (i );
142+ if (idObject instanceof BytesRef ) {
143+ idObject = ((BytesRef ) idObject ).utf8ToString ();
144+ }
145+ id = Uid .encodeId (idObject .toString ());
146+ }
147+ bytesRefs [i ] = id ;
148+ }
149+ return new TermInSetQuery (name (), bytesRefs );
121150 }
122151 // 5.x index, _uid is indexed
123152 return new TermInSetQuery (UidFieldMapper .NAME , Uid .createUidsForTypesAndIds (context .queryTypes (), values ));
@@ -128,13 +157,106 @@ public IndexFieldData.Builder fielddataBuilder() {
128157 if (indexOptions () == IndexOptions .NONE ) {
129158 throw new IllegalArgumentException ("Fielddata access on the _uid field is disallowed" );
130159 }
131- return new PagedBytesIndexFieldData .Builder (
160+ final IndexFieldData . Builder fieldDataBuilder = new PagedBytesIndexFieldData .Builder (
132161 TextFieldMapper .Defaults .FIELDDATA_MIN_FREQUENCY ,
133162 TextFieldMapper .Defaults .FIELDDATA_MAX_FREQUENCY ,
134163 TextFieldMapper .Defaults .FIELDDATA_MIN_SEGMENT_SIZE );
164+ return new IndexFieldData .Builder () {
165+ @ Override
166+ public IndexFieldData <?> build (IndexSettings indexSettings , MappedFieldType fieldType , IndexFieldDataCache cache ,
167+ CircuitBreakerService breakerService , MapperService mapperService ) {
168+ final IndexFieldData <?> fieldData = fieldDataBuilder .build (indexSettings , fieldType , cache , breakerService , mapperService );
169+ if (indexSettings .getIndexVersionCreated ().before (Version .V_6_0_0_alpha3 )) {
170+ // ids were indexed as utf-8
171+ return fieldData ;
172+ }
173+ return new IndexFieldData <AtomicFieldData >() {
174+
175+ @ Override
176+ public Index index () {
177+ return fieldData .index ();
178+ }
179+
180+ @ Override
181+ public String getFieldName () {
182+ return fieldData .getFieldName ();
183+ }
184+
185+ @ Override
186+ public AtomicFieldData load (LeafReaderContext context ) {
187+ return wrap (fieldData .load (context ));
188+ }
189+
190+ @ Override
191+ public AtomicFieldData loadDirect (LeafReaderContext context ) throws Exception {
192+ return wrap (fieldData .loadDirect (context ));
193+ }
194+
195+ @ Override
196+ public SortField sortField (Object missingValue , MultiValueMode sortMode , Nested nested , boolean reverse ) {
197+ XFieldComparatorSource source = new BytesRefFieldComparatorSource (this , missingValue , sortMode , nested );
198+ return new SortField (getFieldName (), source , reverse );
199+ }
200+
201+ @ Override
202+ public void clear () {
203+ fieldData .clear ();
204+ }
205+
206+ };
207+ }
208+ };
135209 }
136210 }
137211
212+ private static AtomicFieldData wrap (AtomicFieldData in ) {
213+ return new AtomicFieldData () {
214+
215+ @ Override
216+ public void close () {
217+ in .close ();
218+ }
219+
220+ @ Override
221+ public long ramBytesUsed () {
222+ return in .ramBytesUsed ();
223+ }
224+
225+ @ Override
226+ public ScriptDocValues <?> getScriptValues () {
227+ return new ScriptDocValues .Strings (getBytesValues ());
228+ }
229+
230+ @ Override
231+ public SortedBinaryDocValues getBytesValues () {
232+ SortedBinaryDocValues inValues = in .getBytesValues ();
233+ return new SortedBinaryDocValues () {
234+
235+ @ Override
236+ public BytesRef nextValue () throws IOException {
237+ BytesRef encoded = inValues .nextValue ();
238+ return new BytesRef (Uid .decodeId (
239+ Arrays .copyOfRange (encoded .bytes , encoded .offset , encoded .offset + encoded .length )));
240+ }
241+
242+ @ Override
243+ public int docValueCount () {
244+ final int count = inValues .docValueCount ();
245+ // If the count is not 1 then the impl is not correct as the binary representation
246+ // does not preserve order. But id fields only have one value per doc so we are good.
247+ assert count == 1 ;
248+ return inValues .docValueCount ();
249+ }
250+
251+ @ Override
252+ public boolean advanceExact (int doc ) throws IOException {
253+ return inValues .advanceExact (doc );
254+ }
255+ };
256+ }
257+ };
258+ }
259+
138260 static MappedFieldType defaultFieldType (IndexSettings indexSettings ) {
139261 MappedFieldType defaultFieldType = Defaults .FIELD_TYPE .clone ();
140262 if (indexSettings .isSingleType ()) {
@@ -166,8 +288,12 @@ public void postParse(ParseContext context) throws IOException {}
166288 @ Override
167289 protected void parseCreateField (ParseContext context , List <IndexableField > fields ) throws IOException {
168290 if (fieldType .indexOptions () != IndexOptions .NONE || fieldType .stored ()) {
169- Field id = new Field (NAME , context .sourceToParse ().id (), fieldType );
170- fields .add (id );
291+ if (context .mapperService ().getIndexSettings ().getIndexVersionCreated ().onOrAfter (Version .V_6_0_0_alpha3 )) {
292+ BytesRef id = Uid .encodeId (context .sourceToParse ().id ());
293+ fields .add (new Field (NAME , id , fieldType ));
294+ } else {
295+ fields .add (new Field (NAME , context .sourceToParse ().id (), fieldType ));
296+ }
171297 }
172298 }
173299
0 commit comments