|
@@ -26,8 +26,6 @@ import org.elasticsearch.test.ESSingleNodeTestCase;
|
|
|
import org.elasticsearch.xpack.core.XPackPlugin;
|
|
|
import org.elasticsearch.xpack.vectors.Vectors;
|
|
|
|
|
|
-import org.junit.Before;
|
|
|
-
|
|
|
import java.io.IOException;
|
|
|
import java.util.Collection;
|
|
|
|
|
@@ -35,67 +33,93 @@ import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.instanceOf;
|
|
|
|
|
|
public class DenseVectorFieldMapperTests extends ESSingleNodeTestCase {
|
|
|
- private DocumentMapper mapper;
|
|
|
+ @Override
|
|
|
+ protected Collection<Class<? extends Plugin>> getPlugins() {
|
|
|
+ return pluginList(Vectors.class, XPackPlugin.class);
|
|
|
+ }
|
|
|
|
|
|
- @Before
|
|
|
- public void setUpMapper() throws Exception {
|
|
|
- IndexService indexService = createIndex("test-index");
|
|
|
+ public void testMappingExceedDimsLimit() throws IOException {
|
|
|
+ IndexService indexService = createIndex("test-index");
|
|
|
DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
|
|
|
String mapping = Strings.toString(XContentFactory.jsonBuilder()
|
|
|
.startObject()
|
|
|
- .startObject("_doc")
|
|
|
- .startObject("properties")
|
|
|
- .startObject("my-dense-vector").field("type", "dense_vector")
|
|
|
- .endObject()
|
|
|
- .endObject()
|
|
|
- .endObject()
|
|
|
+ .startObject("_doc")
|
|
|
+ .startObject("properties")
|
|
|
+ .startObject("my-dense-vector").field("type", "dense_vector").field("dims", DenseVectorFieldMapper.MAX_DIMS_COUNT + 1)
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
.endObject());
|
|
|
- mapper = parser.parse("_doc", new CompressedXContent(mapping));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected Collection<Class<? extends Plugin>> getPlugins() {
|
|
|
- return pluginList(Vectors.class, XPackPlugin.class);
|
|
|
+ MapperParsingException e = expectThrows(MapperParsingException.class, () -> parser.parse("_doc", new CompressedXContent(mapping)));
|
|
|
+ assertEquals(e.getMessage(), "The number of dimensions for field [my-dense-vector] should be in the range [1, 1024]");
|
|
|
}
|
|
|
|
|
|
public void testDefaults() throws Exception {
|
|
|
- float[] expectedArray = {-12.1f, 100.7f, -4};
|
|
|
+ IndexService indexService = createIndex("test-index");
|
|
|
+ DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
|
|
|
+ String mapping = Strings.toString(XContentFactory.jsonBuilder()
|
|
|
+ .startObject()
|
|
|
+ .startObject("_doc")
|
|
|
+ .startObject("properties")
|
|
|
+ .startObject("my-dense-vector").field("type", "dense_vector").field("dims", 3)
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
+ .endObject());
|
|
|
+ DocumentMapper mapper = parser.parse("_doc", new CompressedXContent(mapping));
|
|
|
+
|
|
|
+ float[] validVector = {-12.1f, 100.7f, -4};
|
|
|
ParsedDocument doc1 = mapper.parse(new SourceToParse("test-index", "_doc", "1", BytesReference
|
|
|
.bytes(XContentFactory.jsonBuilder()
|
|
|
.startObject()
|
|
|
- .startArray("my-dense-vector").value(expectedArray[0]).value(expectedArray[1]).value(expectedArray[2]).endArray()
|
|
|
+ .startArray("my-dense-vector").value(validVector[0]).value(validVector[1]).value(validVector[2]).endArray()
|
|
|
.endObject()),
|
|
|
XContentType.JSON));
|
|
|
IndexableField[] fields = doc1.rootDoc().getFields("my-dense-vector");
|
|
|
assertEquals(1, fields.length);
|
|
|
assertThat(fields[0], instanceOf(BinaryDocValuesField.class));
|
|
|
-
|
|
|
// assert that after decoding the indexed value is equal to expected
|
|
|
- BytesRef vectorBR = ((BinaryDocValuesField) fields[0]).binaryValue();
|
|
|
+ BytesRef vectorBR = fields[0].binaryValue();
|
|
|
float[] decodedValues = VectorEncoderDecoder.decodeDenseVector(vectorBR);
|
|
|
assertArrayEquals(
|
|
|
"Decoded dense vector values is not equal to the indexed one.",
|
|
|
- expectedArray,
|
|
|
+ validVector,
|
|
|
decodedValues,
|
|
|
0.001f
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- public void testDimensionLimit() throws IOException {
|
|
|
- float[] validVector = new float[DenseVectorFieldMapper.MAX_DIMS_COUNT];
|
|
|
- BytesReference validDoc = BytesReference.bytes(
|
|
|
- XContentFactory.jsonBuilder().startObject()
|
|
|
- .array("my-dense-vector", validVector)
|
|
|
+ public void testDocumentsWithIncorrectDims() throws Exception {
|
|
|
+ IndexService indexService = createIndex("test-index");
|
|
|
+ int dims = 3;
|
|
|
+ DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
|
|
|
+ String mapping = Strings.toString(XContentFactory.jsonBuilder()
|
|
|
+ .startObject()
|
|
|
+ .startObject("_doc")
|
|
|
+ .startObject("properties")
|
|
|
+ .startObject("my-dense-vector").field("type", "dense_vector").field("dims", dims)
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
+ .endObject()
|
|
|
.endObject());
|
|
|
- mapper.parse(new SourceToParse("test-index", "_doc", "1", validDoc, XContentType.JSON));
|
|
|
+ DocumentMapper mapper = parser.parse("_doc", new CompressedXContent(mapping));
|
|
|
|
|
|
- float[] invalidVector = new float[DenseVectorFieldMapper.MAX_DIMS_COUNT + 1];
|
|
|
- BytesReference invalidDoc = BytesReference.bytes(
|
|
|
- XContentFactory.jsonBuilder().startObject()
|
|
|
- .array("my-dense-vector", invalidVector)
|
|
|
- .endObject());
|
|
|
+ // test that error is thrown when a document has number of dims more than defined in the mapping
|
|
|
+ float[] invalidVector = new float[dims + 1];
|
|
|
+ BytesReference invalidDoc = BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
|
|
|
+ .array("my-dense-vector", invalidVector)
|
|
|
+ .endObject());
|
|
|
MapperParsingException e = expectThrows(MapperParsingException.class, () -> mapper.parse(
|
|
|
new SourceToParse("test-index", "_doc", "1", invalidDoc, XContentType.JSON)));
|
|
|
- assertThat(e.getDetailedMessage(), containsString("has exceeded the maximum allowed number of dimensions"));
|
|
|
+ assertThat(e.getCause().getMessage(), containsString("has exceeded the number of dimensions [3] defined in mapping"));
|
|
|
+
|
|
|
+ // test that error is thrown when a document has number of dims less than defined in the mapping
|
|
|
+ float[] invalidVector2 = new float[dims - 1];
|
|
|
+ BytesReference invalidDoc2 = BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
|
|
|
+ .array("my-dense-vector", invalidVector2)
|
|
|
+ .endObject());
|
|
|
+ MapperParsingException e2 = expectThrows(MapperParsingException.class, () -> mapper.parse(
|
|
|
+ new SourceToParse("test-index", "_doc", "2", invalidDoc2, XContentType.JSON)));
|
|
|
+ assertThat(e2.getCause().getMessage(), containsString("has number of dimensions [2] less than defined in the mapping [3]"));
|
|
|
}
|
|
|
}
|