Skip to main content
Loading

Java client

Overviewโ€‹

This page describes how to create AI applications with the gRPC API and Java client provided with Aerospike Vector Search (AVS).

Prerequisitesโ€‹

  • Java 17 (Java client 0.4.0 and later)
  • Java 21 (Java client 0.3.0 and earlier)

Java client componentsโ€‹

The AVS Java client contains the following components:

Client

  • Client: AVS client used for index management, user management, inserting vectors, performing search operations, and checking index statuses.

Utility classes

  • Conversions: Utility functions that convert data into the format accepted by AVS and transform retrieved data into JVM (Java Virtual Machine) types.
  • HostPort: A data structure that represents AVS server information including hostname and port.
  • ConnectionConfig: A data structure that outlines details related to connection settings such as endpoints, credentials, and timeouts.
  • ClientTlsConfig: A data structure designed to encapsulate TLS (Transport Layer Security) configuration settings for secure communication.
  • Projection: Query projection for specifying which parts of the documents to retrieve during search operations.
  • StaticRoles: Represents a set of predefined user roles within the system, facilitating role-based access control.
  • VectorSearchQuery: A data structure that represents parameters and criteria for performing vector search queries using Vector.
  • KeySearchQuery: A data structure that represents parameters and criteria for performing vector search queries using Key.

Importing the Java clientโ€‹

  1. To import the client into your application, add the following dependency to your pom.xml:

    <!-- Aerospike client dependencies -->
    <dependency>
    <groupId>com.aerospike</groupId>
    <artifactId>avs-client-java</artifactId>
    <version>1.0.0</version>
    </dependency>

    The artifacts are available on Maven.

  2. Import corresponding dependencies with the following:

    import com.aerospike.vector.client.*;
    import com.aerospike.vector.client.dbclient.Client;
    import com.aerospike.vector.client.dbclient.VectorSearchListener;

Client operationsโ€‹

This section provides example code for client operations.

Create a client:

// create a client connection with admin privileges
com.aerospike.vector.client.auth.PasswordCredentials cred = new com.aerospike.vector.client.auth.PasswordCredentials("admin", "admin");

// connection config
ConnectionConfig config =
new ConnectionConfig.ConnectionConfigBuilder()
.seeds(TestConfigProvider.HOSTS)
.listenerName("listener")
.isLoadBalancer(true)
.credentials(cred)
.connectTimeout(10000)
.clientTlsConfig(tlsConfig) // if mtls/tls connection required
.build();

Client client = new Client(config);

Create an AVS index:

client.indexCreate(indexId, "vector", 128, VectorDistanceMetric.DOT_PRODUCT, null, HnswParams.newBuilder().build(), 
IndexStorage.newBuilder().setNamespace(DEFAULT_NAMESPACE).build(),
Map.of(), 60_000);

List available indexes in AVS:

client.indexList();

Drop a specific index:

client.indexDrop(indexId);

Retrieve the current status of an index:

client.indexStatus(indexId);

Add a vector in AVS:

/*
* namespace: Aerospike namespace to store the record
* set: Aerospike set to be used for storing record
* key: key of the record
* map: Map< String, Object> contains bins and the corresponding values
* ignoreMemQueueFull: boolean
* writeType: record write type
*/
client.put(namespace, set, key, Map.of("vector_bin_name", vector, 0), false, WriteType.forNumber(0));

Retrieve an AVS record using a key:

client.get(namespace, set, key, Projection.DEFAULT);

Check if an inserted vector record is indexed:

client.isIndexed(namespace, set, key, index_namespace, indexName);

Vector search using Vectorโ€‹

You can perform a simple vector search with the following:

/*
* listener: a callback which acts upon intermediate states and can collect searched data
* namespace: Aerospike namespace
* indexname: name of the AVS index name
* searchvector: a float array which gets converted to aerospike specific format
* limit: specifies number of records to be returned as search result
* projection: result projection
*/
VectorSearchQuery query = new VectorSearchQuery.Builder(namespace, indexname,
searchvector, limit).withProjection(Projection.getDefault()).build();
client.vectorSearchAsync(query, listener);

The following illustrates a simple listener implementation:

class SimpleListener implements VectorSearchListener {
List<Neighbor>[] results;
int idx;
AtomicLong counter;

public SimpleListener(int idx, List<Neighbor>[] results, AtomicLong counter) {
this.results = results;
this.idx = idx;
this.counter = counter;
}

List<Neighbor> result = new ArrayList<>();

@Override
public void onNext(Neighbor neighbor) {
result.add(neighbor);
}

@Override
public void onComplete() {
results[idx] = result;
counter.incrementAndGet();
}

@Override
public void onError(Throwable e) {
LOG.warn("Error in listener {}", e);
}
}

Vector search using Keyโ€‹

Perform a vector search using record key:

/**
* The KeySearchQuery class defines query search parameters in an Aerospike vector index using a specific user-defined key.
* The searchByKey API returns a list of neighbors. However, if the key is not present in AVS
* then this query returns null.
*/

KeySearchQuery keySearchQuery =
KeySearchQuery.builder()
.userKey(String.valueOf(i)) //key
.namespace("test")
.indexName("index")
.set("index_set")
.limit(100)
.build();

// client.put() example above uses "vector_bin_name" field to hint where the vector is stored in the record key.
result = client.searchByKey(keySearchQuery, "vector_bin_name");

Get vector data as a float listโ€‹

You can get an entry with the following call:

// getRecord() contains all bins returned from AVS
List<Float> floatList = result.getRecord().getFields(0).getValue().getVectorValue().getFloatData().getValueList();

Support matrixโ€‹

AVS versionClient versionRequired Java version
0.10.01.0.017
0.10.00.5.017
0.9.00.4.117
0.9.00.4.017
0.9.00.3.021
0.4.00.2.021

Javadocsโ€‹

For a more detailed description of the APIs, see the Javadoc documentation.