All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aerospike.vector.client.Conversions Maven / Gradle / Ivy

Go to download

This project includes the Java client for Aerospike Vector Search for high-performance data interactions.

The newest version!
package com.aerospike.vector.client;

import com.aerospike.vector.client.proto.*;
import com.google.protobuf.ByteString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Utility class to convert data suitable for AVS. User would rarely need to invoke them directly.
 */

public class Conversions {
    private static final Logger log = LoggerFactory.getLogger(Conversions.class);

    private Conversions(){};

    /**
     * Constructs a record key using Aerospike namespace, set and key. User may not need to these function directly
     * Key must be of type String, byte[], Integer
     * @param namespace Aerospike namespace
     * @param set Aerospike set
     * @param key key, must be of type String, byte[] or Integer
     * @return key {@link Key}
     */
    public static Key buildKey(String namespace, String set, Object key) {
        Key.Builder builder = Key.newBuilder().setNamespace(namespace);
        if (set != null) {
            builder.setSet(set);
        }

        if (key instanceof String) {
            builder.setStringValue((String) key);
        } else if (key instanceof byte[]) {
            builder.setBytesValue(ByteString.copyFrom((byte[]) key));
        } else if (key instanceof Integer) {
            builder.setIntValue((Integer) key);
        } else if (key instanceof Long) {
            builder.setLongValue((Long) key);
        } else {
            throw new IllegalArgumentException("Unsupported key type: " + key.getClass().getName());
        }

        return builder.build();
    }

    /**
     * Constructs a {@link Field} using bin name and value
     * @param name bin name in the aerospike
     * @param value corresponding value in the bin
     * @return {@link Field}
     */
    public static com.aerospike.vector.client.proto.Field buildField(String name, Object value) {
        return com.aerospike.vector.client.proto.Field.newBuilder()
                .setName(name)
                .setValue(toVectorDbValue(value))
                .build();
    }

    private static Value toVectorDbValue(Object value) {
        log.debug("buildValue value:{} class type: {} " , value, value.getClass().getName() );

        Value.Builder builder = Value.newBuilder();
        if (value instanceof String) {
            builder.setStringValue((String) value);
        } else if (value instanceof byte[]) {
            builder.setBytesValue(ByteString.copyFrom((byte[]) value));
        } else if (value instanceof Integer) {
            builder.setIntValue((Integer) value);
        } else if (value instanceof Long) {
            builder.setLongValue((Long) value);
        } else if (value instanceof Float) {
            builder.setFloatValue((Float) value);
        } else if (value instanceof Double) {
            builder.setDoubleValue((Double) value);
        } else if (value instanceof float[]) {
            builder.setVectorValue(buildVectorValue(value));
        } else if (value instanceof double[]) {
            builder.setVectorValue(buildVectorValue(value));
        } else if (value instanceof boolean[]) {
            builder.setVectorValue(buildVectorValue(value));
        } else if (value instanceof List) {
            builder.setListValue(buildListValue((List) value));
        } else if (value instanceof Map) {
            builder.setMapValue(buildMapValue((Map) value));
        } else {
            throw new IllegalArgumentException("Unsupported value type: " + value.getClass().getName());
        }
        return builder.build();
    }

    private static com.aerospike.vector.client.proto.List buildListValue(List list) {
        return com.aerospike.vector.client.proto.List.newBuilder()
                .addAllEntries(list.stream()
                        .filter(Objects::nonNull)
                        .map(Conversions::toVectorDbValue)
                        .collect(Collectors.toList()))
                .build();
    }

    private static com.aerospike.vector.client.proto.Map buildMapValue(Map map) {
        return com.aerospike.vector.client.proto.Map.newBuilder()
                .addAllEntries(map.entrySet().stream()
                        .map(entry -> MapEntry.newBuilder()
                                .setKey(toMapKey(entry.getKey()))
                                .setValue(toVectorDbValue(entry.getValue()))
                                .build())
                        .collect(Collectors.toList()))
                .build();
    }

    /**
     * Constructs a {@link Vector} from an array of booleans or floats, used for vector search.
     * This method supports creating vectors from either float or boolean arrays by detecting the type of the input array.
     * Depending on the type, it constructs the appropriate {@link Vector} using either {@link FloatData} or {@link BoolData}.
     *
     * 

For examples of usage, see the test method {@code testVectorSearchAsync} in the VectorSearchTest class: *

     * src/test/java/com/aerospike/vector/client/internal/VectorSearchTest.java
     * 
* If available online, you can view this file at: * VectorSearchTest * * @param array an array of floats or booleans to be converted into a {@link Vector} * @return a {@link Vector} containing the data from the provided array * @throws RuntimeException if the array type is neither float[] nor boolean[] */ public static Vector buildVectorValue(Object array) { if (array instanceof float[]) { float[] floats = (float[]) array; Vector.Builder vectorBuilder = Vector.newBuilder(); FloatData.Builder floatDataBuilder = FloatData.newBuilder(); for (float value : floats) { floatDataBuilder.addValue(value); } vectorBuilder.setFloatData(floatDataBuilder); return vectorBuilder.build(); }else if(array instanceof boolean[]){ boolean[] bools = (boolean[]) array; Vector.Builder vectorBuilder = Vector.newBuilder(); BoolData.Builder booleanDataBuilder = BoolData.newBuilder(); for (boolean value : bools) { booleanDataBuilder.addValue(value); } vectorBuilder.setBoolData(booleanDataBuilder); return vectorBuilder.build(); } else{ log.error("Found unexpected type :{}", array.getClass().getName()); throw new RuntimeException("Found unexpected type"); } } private static MapKey toMapKey(Object key) { MapKey.Builder builder = MapKey.newBuilder(); if (key instanceof String) { builder.setStringValue((String) key); } else if (key instanceof Integer) { builder.setIntValue((Integer) key); } else if (key instanceof Long) { builder.setLongValue((Long) key); } else if (key instanceof Float) { builder.setFloatValue((Float) key); } else if (key instanceof Double) { builder.setDoubleValue((Double) key); } else { throw new IllegalArgumentException("Unsupported map key type: " + key.getClass().getName()); } return builder.build(); } /** * Converts a Protobuf MapKey object to a Java object. * @param mapKey The Protobuf MapKey object to convert. * @return The Java object representing the key. */ public static Object fromMapKey(MapKey mapKey) { if (mapKey.hasStringValue()) { return mapKey.getStringValue(); } else if (mapKey.hasIntValue()) { return mapKey.getIntValue(); } else if (mapKey.hasLongValue()) { return mapKey.getLongValue(); } else if (mapKey.hasFloatValue()) { return mapKey.getFloatValue(); } else if (mapKey.hasDoubleValue()) { return mapKey.getDoubleValue(); } else { throw new IllegalStateException("Unsupported map key type"); } } /** * Converts the data extracted from Vector DB {@link Value} to standard java types. * @param value {@link Value} types * @return java types extracted from {@link Value} types */ public static Object fromVectorDBValue(Value value) { Object local = null; if (value.hasStringValue()) { local = value.getStringValue(); } else if (value.hasBytesValue()) { local = value.getBytesValue().toByteArray(); } else if (value.hasIntValue()) { local = value.getIntValue(); } else if (value.hasLongValue()) { local = value.getLongValue(); } else if (value.hasFloatValue()) { local = value.getFloatValue(); } else if (value.hasDoubleValue()) { local = value.getDoubleValue(); } else if (value.hasMapValue()) { local = value.getMapValue().getEntriesList().stream() .collect(Collectors.toMap( entry -> fromMapKey(entry.getKey()), entry -> fromVectorDBValue(entry.getValue()) )); } else if (value.hasListValue()) { local = value.getListValue().getEntriesList().stream() .map(entry -> fromVectorDBValue(entry)) .collect(Collectors.toList()); } else { if (value.hasVectorValue()) { if (value.getVectorValue().hasFloatData()) { local = value.getVectorValue().getFloatData().getValueList().stream().map(x -> x.floatValue()).collect(Collectors.toList()); } else { local = value.getVectorValue().getBoolData().getValueList().stream().map(x -> x.booleanValue()).collect(Collectors.toList()); } } else { log.warn("Found null in Value: {} object", value); } } return local; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy