Skip to content

Commit 354e6e6

Browse files
committed
Add a de-duplicating flat vector format
1 parent db3222d commit 354e6e6

13 files changed

Lines changed: 1993 additions & 24 deletions

lucene/core/src/java/module-info.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
exports org.apache.lucene.analysis.tokenattributes;
2626
exports org.apache.lucene.analysis;
2727
exports org.apache.lucene.codecs.compressing;
28+
exports org.apache.lucene.codecs.dedup;
2829
exports org.apache.lucene.codecs.lucene90.compressing;
2930
exports org.apache.lucene.codecs.lucene90;
3031
exports org.apache.lucene.codecs.lucene94;
@@ -86,7 +87,8 @@
8687
provides org.apache.lucene.codecs.KnnVectorsFormat with
8788
org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat,
8889
org.apache.lucene.codecs.lucene104.Lucene104ScalarQuantizedVectorsFormat,
89-
org.apache.lucene.codecs.lucene104.Lucene104HnswScalarQuantizedVectorsFormat;
90+
org.apache.lucene.codecs.lucene104.Lucene104HnswScalarQuantizedVectorsFormat,
91+
org.apache.lucene.codecs.dedup.DedupFlatVectorsFormat;
9092
provides org.apache.lucene.codecs.PostingsFormat with
9193
org.apache.lucene.codecs.lucene104.Lucene104PostingsFormat;
9294
provides org.apache.lucene.index.SortFieldProvider with
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.lucene.codecs.dedup;
19+
20+
import java.io.IOException;
21+
import org.apache.lucene.codecs.hnsw.FlatVectorScorerUtil;
22+
import org.apache.lucene.codecs.hnsw.FlatVectorsFormat;
23+
import org.apache.lucene.codecs.hnsw.FlatVectorsReader;
24+
import org.apache.lucene.codecs.hnsw.FlatVectorsScorer;
25+
import org.apache.lucene.codecs.hnsw.FlatVectorsWriter;
26+
import org.apache.lucene.index.SegmentReadState;
27+
import org.apache.lucene.index.SegmentWriteState;
28+
29+
/**
30+
* A {@link FlatVectorsFormat} that de-duplicates stored vectors across all fields in a segment.
31+
* Unique vectors are stored once in a shared dictionary (.dvd), and each field maintains a compact
32+
* ordinal mapping from its document ords to dictionary ords (.dvm/.dvd).
33+
*
34+
* <h2>.dvd (dedup vector data) file</h2>
35+
*
36+
* <ul>
37+
* <li>Shared dictionary: unique vectors stored contiguously, accessible by dictOrd
38+
* <li>Per-field ord-to-dictOrd mappings (vint encoded)
39+
* <li>Per-field OrdToDoc DISI data (for sparse fields)
40+
* </ul>
41+
*
42+
* <h2>.dvm (dedup vector meta) file</h2>
43+
*
44+
* <ul>
45+
* <li>Dictionary size (number of unique vectors), dimension, vector encoding
46+
* <li>Per-field: field number, size, ordToDoc config, map offset/length
47+
* <li>-1 sentinel marking end of fields
48+
* </ul>
49+
*
50+
* <p>During merge, vectors are streamed one at a time. Only a hash map of {@code long hash → int
51+
* dictOrd} is held in memory (~12 bytes per unique vector). Vector data is never buffered.
52+
*
53+
* @lucene.experimental
54+
*/
55+
public final class DedupFlatVectorsFormat extends FlatVectorsFormat {
56+
57+
public static final String NAME = "DedupFlatVectorsFormat";
58+
59+
static final String META_CODEC_NAME = "DedupFlatVectorsFormatMeta";
60+
static final String DATA_CODEC_NAME = "DedupFlatVectorsFormatData";
61+
static final String META_EXTENSION = "dvm";
62+
static final String DATA_EXTENSION = "dvd";
63+
64+
static final int VERSION_START = 0;
65+
static final int VERSION_CURRENT = VERSION_START;
66+
67+
private final FlatVectorsScorer vectorsScorer;
68+
69+
/** Creates a dedup format with the default scorer. */
70+
public DedupFlatVectorsFormat() {
71+
this(FlatVectorScorerUtil.getLucene99FlatVectorsScorer());
72+
}
73+
74+
/** Creates a dedup format with the given scorer. */
75+
public DedupFlatVectorsFormat(FlatVectorsScorer vectorsScorer) {
76+
super(NAME);
77+
this.vectorsScorer = vectorsScorer;
78+
}
79+
80+
@Override
81+
public FlatVectorsWriter fieldsWriter(SegmentWriteState state) throws IOException {
82+
return new DedupFlatVectorsWriter(state, vectorsScorer);
83+
}
84+
85+
@Override
86+
public FlatVectorsReader fieldsReader(SegmentReadState state) throws IOException {
87+
return new DedupFlatVectorsReader(state, vectorsScorer);
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return "DedupFlatVectorsFormat(vectorsScorer=" + vectorsScorer + ")";
93+
}
94+
}

0 commit comments

Comments
 (0)