|  | 
| 7 | 7 | 
 | 
| 8 | 8 | package org.elasticsearch.xpack.countedkeyword; | 
| 9 | 9 | 
 | 
| 10 |  | -import org.apache.lucene.document.BinaryDocValuesField; | 
| 11 | 10 | import org.apache.lucene.document.FieldType; | 
| 12 | 11 | import org.apache.lucene.index.BinaryDocValues; | 
| 13 | 12 | import org.apache.lucene.index.DocValues; | 
|  | 
| 19 | 18 | import org.apache.lucene.index.TermsEnum; | 
| 20 | 19 | import org.apache.lucene.search.SortField; | 
| 21 | 20 | import org.apache.lucene.util.BytesRef; | 
|  | 21 | +import org.elasticsearch.ElasticsearchException; | 
| 22 | 22 | import org.elasticsearch.common.bytes.BytesArray; | 
| 23 | 23 | import org.elasticsearch.common.io.stream.ByteArrayStreamInput; | 
| 24 | 24 | import org.elasticsearch.common.io.stream.BytesStreamOutput; | 
|  | 
| 31 | 31 | import org.elasticsearch.index.fielddata.plain.AbstractIndexOrdinalsFieldData; | 
| 32 | 32 | import org.elasticsearch.index.fielddata.plain.AbstractLeafOrdinalsFieldData; | 
| 33 | 33 | import org.elasticsearch.index.mapper.BinaryFieldMapper; | 
|  | 34 | +import org.elasticsearch.index.mapper.CustomDocValuesField; | 
| 34 | 35 | import org.elasticsearch.index.mapper.DocumentParserContext; | 
| 35 | 36 | import org.elasticsearch.index.mapper.FieldMapper; | 
| 36 | 37 | import org.elasticsearch.index.mapper.KeywordFieldMapper; | 
| @@ -437,15 +438,17 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio | 
| 437 | 438 |             return; | 
| 438 | 439 |         } | 
| 439 | 440 | 
 | 
| 440 |  | -        int i = 0; | 
| 441 |  | -        int[] counts = new int[values.size()]; | 
| 442 |  | -        for (Map.Entry<String, Integer> value : values.entrySet()) { | 
| 443 |  | -            context.doc().add(new KeywordFieldMapper.KeywordField(fullPath(), new BytesRef(value.getKey()), fieldType)); | 
| 444 |  | -            counts[i++] = value.getValue(); | 
|  | 441 | +        for (String value : values.keySet()) { | 
|  | 442 | +            context.doc().add(new KeywordFieldMapper.KeywordField(fullPath(), new BytesRef(value), fieldType)); | 
|  | 443 | +        } | 
|  | 444 | +        CountsBinaryDocValuesField field = (CountsBinaryDocValuesField) context.doc().getByKey(countFieldMapper.fieldType().name()); | 
|  | 445 | +        if (field == null) { | 
|  | 446 | +            field = new CountsBinaryDocValuesField(countFieldMapper.fieldType().name()); | 
|  | 447 | +            field.add(values); | 
|  | 448 | +            context.doc().addWithKey(countFieldMapper.fieldType().name(), field); | 
|  | 449 | +        } else { | 
|  | 450 | +            field.add(values); | 
| 445 | 451 |         } | 
| 446 |  | -        BytesStreamOutput streamOutput = new BytesStreamOutput(); | 
| 447 |  | -        streamOutput.writeVIntArray(counts); | 
| 448 |  | -        context.doc().add(new BinaryDocValuesField(countFieldMapper.fullPath(), streamOutput.bytes().toBytesRef())); | 
| 449 | 452 |     } | 
| 450 | 453 | 
 | 
| 451 | 454 |     private void parseArray(DocumentParserContext context, SortedMap<String, Integer> values) throws IOException { | 
| @@ -512,4 +515,37 @@ protected SyntheticSourceSupport syntheticSourceSupport() { | 
| 512 | 515 |         ); | 
| 513 | 516 |     } | 
| 514 | 517 | 
 | 
|  | 518 | +    private class CountsBinaryDocValuesField extends CustomDocValuesField { | 
|  | 519 | +        private final SortedMap<String, Integer> counts; | 
|  | 520 | + | 
|  | 521 | +        CountsBinaryDocValuesField(String name) { | 
|  | 522 | +            super(name); | 
|  | 523 | +            counts = new TreeMap<>(); | 
|  | 524 | +        } | 
|  | 525 | + | 
|  | 526 | +        public void add(SortedMap<String, Integer> newCounts) { | 
|  | 527 | +            for (Map.Entry<String, Integer> currCount : newCounts.entrySet()) { | 
|  | 528 | +                this.counts.put(currCount.getKey(), this.counts.getOrDefault(currCount.getKey(), 0) + currCount.getValue()); | 
|  | 529 | +            } | 
|  | 530 | +        } | 
|  | 531 | + | 
|  | 532 | +        @Override | 
|  | 533 | +        public BytesRef binaryValue() { | 
|  | 534 | +            try { | 
|  | 535 | +                int maxBytesPerVInt = 5; | 
|  | 536 | +                int bytesSize = (counts.size() + 1) * maxBytesPerVInt; | 
|  | 537 | +                BytesStreamOutput out = new BytesStreamOutput(bytesSize); | 
|  | 538 | +                int countsArr[] = new int[counts.size()]; | 
|  | 539 | +                int i = 0; | 
|  | 540 | +                for (Integer currCount : counts.values()) { | 
|  | 541 | +                    countsArr[i++] = currCount; | 
|  | 542 | +                } | 
|  | 543 | +                out.writeVIntArray(countsArr); | 
|  | 544 | +                return out.bytes().toBytesRef(); | 
|  | 545 | +            } catch (IOException e) { | 
|  | 546 | +                throw new ElasticsearchException("Failed to get binary value", e); | 
|  | 547 | +            } | 
|  | 548 | +        } | 
|  | 549 | +    } | 
|  | 550 | + | 
| 515 | 551 | } | 
0 commit comments