Skip to content

Using GLIDE Modules

Valkey Modules extend Valkey’s core commands and functionality. Starting in GLIDE 1.2, commonly used modules, like JSON and Vector Search, are supported through a dedicated wrapper interface.

The Modules API provides convenient wrapper methods for commonly used Valkey modules. These wrappers are built on top of the Custom Command API, automatically constructing and executing the appropriate module commands. This allows for type-safe methods, parameter validation, and IDE autocomplete support. Under the hood, each wrapper method translates your call into the corresponding module command and executes it via the Custom Commands API.

Currently, GLIDE supports dedicated interfaces for:

Before using a module, including the supported modules, it will need to be loaded into Valkey. See Modules Introduction on how to load modules into your Valkey service.

import glide.api.commands.servermodules.Json;
try (GlideClient glideClient = GlideClient.createClient(config).get()) {
String key = "testKey";
String path = "$";
String jsonValue = "{\"a\": 1.0, \"b\": 2}";
CompletableFuture<String> setResponseFuture = Json.set(glideClient, key, path, jsonValue);
String setResponse = setResponseFuture.get(); // "OK"
assert setResponse.equals("OK");
CompletableFuture<String> getResponseFuture = Json.get(client, key).get();
String getResponseFuture = setResponseFuture.get(); // jsonValue
assert value.equals("{\"a\": 1.0, \"b\": 2}");
}
import glide.api.commands.servermodules.FT;
import glide.api.models.commands.FT.FTCreateOptions.FieldInfo;
import glide.api.models.commands.FT.FTCreateOptions;
import glide.api.models.commands.FT.FTCreateOptions.*;
import glide.api.models.commands.FT.FTSearchOptions;
try (GlideClient glideClient = GlideClient.createClient(config).get()) {
// FT.Create a Hash index with Hash values and FT.Search those values
String prefix = "{hash}:";
String index = prefix + "index";
FieldInfo[] fields = new FieldInfo[] {
new FieldInfo("vec", "VEC", VectorFieldHnsw.builder(DistanceMetric.L2, 2).build())
};
FTCreateOptions.builder().dataType(DataType.HASH).prefixes(new String[] {prefix}).build();
FT.create(client, index, fields, FTCreateOptions).get(); // returns "OK"
Map hash0 = Map.of("vec", new byte[] {
(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0
});
client.hset(prefix + "0", hash0).get();
Map hash1 = Map.of("vec", new byte[] {
(byte) 0, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 0, (byte) 0x80, (byte) 0xBF
});
client.hset(prefix + "1", hash1).get();
Thread.sleep(1000); // let server digest the data and update index
FTSearchOptions searchOptions = FTSearchOptions.builder()
.params(Map.of("query_vec", (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0)))
.build();
String query = "*=>[KNN 2 @VEC $query_vec]";
Object[] ftsearchResponse = FT.search(client, index, query, searchOptions).get();
assert ftsearchResponse[0] == 2L;
// ftsearchResponse[1] contains a map with "{hash}:0" and "{hash}:1" vector search results
}