@Override protected void encode( ByteSequencesWriter writer, ByteArrayDataOutput output, byte[] buffer, BytesRef spare, long weight) throws IOException { if (spare.length + 5 >= buffer.length) { buffer = ArrayUtil.grow(buffer, spare.length + 5); } output.reset(buffer); output.writeBytes(spare.bytes, spare.offset, spare.length); output.writeByte((byte) 0); // separator: not used, just for sort order output.writeInt(encodeWeight(weight)); writer.write(buffer, 0, output.getPosition()); }
@Override public void build(TermFreqIterator tfit) throws IOException { if (tfit instanceof TermFreqPayloadIterator) { throw new IllegalArgumentException("this suggester doesn't support payloads"); } File tempInput = File.createTempFile( FSTCompletionLookup.class.getSimpleName(), ".input", Sort.defaultTempDir()); File tempSorted = File.createTempFile( FSTCompletionLookup.class.getSimpleName(), ".sorted", Sort.defaultTempDir()); Sort.ByteSequencesWriter writer = new Sort.ByteSequencesWriter(tempInput); Sort.ByteSequencesReader reader = null; ExternalRefSorter sorter = null; // Push floats up front before sequences to sort them. For now, assume they are non-negative. // If negative floats are allowed some trickery needs to be done to find their byte order. boolean success = false; try { byte[] buffer = new byte[0]; ByteArrayDataOutput output = new ByteArrayDataOutput(buffer); BytesRef spare; while ((spare = tfit.next()) != null) { if (spare.length + 4 >= buffer.length) { buffer = ArrayUtil.grow(buffer, spare.length + 4); } output.reset(buffer); output.writeInt(encodeWeight(tfit.weight())); output.writeBytes(spare.bytes, spare.offset, spare.length); writer.write(buffer, 0, output.getPosition()); } writer.close(); // We don't know the distribution of scores and we need to bucket them, so we'll sort // and divide into equal buckets. SortInfo info = new Sort().sort(tempInput, tempSorted); tempInput.delete(); FSTCompletionBuilder builder = new FSTCompletionBuilder( buckets, sorter = new ExternalRefSorter(new Sort()), sharedTailLength); final int inputLines = info.lines; reader = new Sort.ByteSequencesReader(tempSorted); long line = 0; int previousBucket = 0; int previousScore = 0; ByteArrayDataInput input = new ByteArrayDataInput(); BytesRef tmp1 = new BytesRef(); BytesRef tmp2 = new BytesRef(); while (reader.read(tmp1)) { input.reset(tmp1.bytes); int currentScore = input.readInt(); int bucket; if (line > 0 && currentScore == previousScore) { bucket = previousBucket; } else { bucket = (int) (line * buckets / inputLines); } previousScore = currentScore; previousBucket = bucket; // Only append the input, discard the weight. tmp2.bytes = tmp1.bytes; tmp2.offset = input.getPosition(); tmp2.length = tmp1.length - input.getPosition(); builder.add(tmp2, bucket); line++; } // The two FSTCompletions share the same automaton. this.higherWeightsCompletion = builder.build(); this.normalCompletion = new FSTCompletion(higherWeightsCompletion.getFST(), false, exactMatchFirst); success = true; } finally { if (success) IOUtils.close(reader, writer, sorter); else IOUtils.closeWhileHandlingException(reader, writer, sorter); tempInput.delete(); tempSorted.delete(); } }
public void index(IndexWriter writer, Type valueType, long[] values, int offset, int num) throws CorruptIndexException, IOException { final Field valField; if (VERBOSE) { System.out.println( "TEST: add docs " + offset + "-" + (offset + num) + " valType=" + valueType); } switch (valueType) { case VAR_INTS: valField = new PackedLongDocValuesField("promote", (long) 0); break; case FIXED_INTS_8: valField = new ByteDocValuesField("promote", (byte) 0); break; case FIXED_INTS_16: valField = new ShortDocValuesField("promote", (short) 0); break; case FIXED_INTS_32: valField = new IntDocValuesField("promote", 0); break; case FIXED_INTS_64: valField = new LongDocValuesField("promote", (byte) 0); break; case FLOAT_32: valField = new FloatDocValuesField("promote", 0f); break; case FLOAT_64: valField = new DoubleDocValuesField("promote", 0d); break; case BYTES_FIXED_STRAIGHT: valField = new StraightBytesDocValuesField("promote", new BytesRef(), true); break; case BYTES_VAR_STRAIGHT: valField = new StraightBytesDocValuesField("promote", new BytesRef(), false); break; case BYTES_FIXED_DEREF: valField = new DerefBytesDocValuesField("promote", new BytesRef(), true); break; case BYTES_VAR_DEREF: valField = new DerefBytesDocValuesField("promote", new BytesRef(), false); break; case BYTES_FIXED_SORTED: valField = new SortedBytesDocValuesField("promote", new BytesRef(), true); break; case BYTES_VAR_SORTED: valField = new SortedBytesDocValuesField("promote", new BytesRef(), false); break; default: throw new IllegalStateException("unknown Type: " + valueType); } for (int i = offset; i < offset + num; i++) { Document doc = new Document(); doc.add(new Field("id", i + "", TextField.TYPE_STORED)); switch (valueType) { case VAR_INTS: // TODO: can we do nextLong()? values[i] = random().nextInt(); valField.setLongValue(values[i]); break; case FIXED_INTS_16: // TODO: negatives too? values[i] = random().nextInt(Short.MAX_VALUE); valField.setShortValue((short) values[i]); break; case FIXED_INTS_32: values[i] = random().nextInt(); valField.setIntValue((int) values[i]); break; case FIXED_INTS_64: values[i] = random().nextLong(); valField.setLongValue(values[i]); break; case FLOAT_64: final double nextDouble = random().nextDouble(); values[i] = Double.doubleToRawLongBits(nextDouble); valField.setDoubleValue(nextDouble); break; case FLOAT_32: final float nextFloat = random().nextFloat(); values[i] = Double.doubleToRawLongBits(nextFloat); valField.setFloatValue(nextFloat); break; case FIXED_INTS_8: values[i] = (byte) i; valField.setByteValue((byte) values[i]); break; case BYTES_FIXED_DEREF: case BYTES_FIXED_SORTED: case BYTES_FIXED_STRAIGHT: values[i] = random().nextLong(); byte bytes[] = new byte[8]; ByteArrayDataOutput out = new ByteArrayDataOutput(bytes, 0, 8); out.writeLong(values[i]); valField.setBytesValue(new BytesRef(bytes)); break; case BYTES_VAR_DEREF: case BYTES_VAR_SORTED: case BYTES_VAR_STRAIGHT: byte lbytes[] = new byte[8]; ByteArrayDataOutput lout = new ByteArrayDataOutput(lbytes, 0, 8); final int len; if (random().nextBoolean()) { values[i] = random().nextInt(); lout.writeInt((int) values[i]); len = 4; } else { values[i] = random().nextLong(); lout.writeLong(values[i]); len = 8; } valField.setBytesValue(new BytesRef(lbytes, 0, len)); break; default: fail("unexpected value " + valueType); } if (VERBOSE) { System.out.println(" doc " + i + " has val=" + valField); } doc.add(valField); writer.addDocument(doc); if (random().nextInt(10) == 0) { writer.commit(); } } }