Skip to content

Commit

Permalink
Java: FT.CREATE (#2414)
Browse files Browse the repository at this point in the history
Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
  • Loading branch information
Yury-Fridlyand authored Oct 11, 2024
1 parent 8fea303 commit bbfce44
Show file tree
Hide file tree
Showing 7 changed files with 747 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Python: Add JSON.ARRLEN command ([#2403](https://github.com/valkey-io/valkey-glide/pull/2403))
* Python: Add JSON.CLEAR command ([#2418](https://github.com/valkey-io/valkey-glide/pull/2418))

* Java: Added `FT.CREATE` ([#2414](https://github.com/valkey-io/valkey-glide/pull/2414))

#### Breaking Changes

#### Fixes
Expand Down
4 changes: 2 additions & 2 deletions java/client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ jar.dependsOn('copyNativeLib')
javadoc.dependsOn('copyNativeLib')
copyNativeLib.dependsOn('buildRustRelease')
compileTestJava.dependsOn('copyNativeLib')
test.dependsOn('buildRust')
testFfi.dependsOn('buildRust')
test.dependsOn('buildRustRelease')
testFfi.dependsOn('buildRustRelease')

test {
exclude "glide/ffi/FfiTest.class"
Expand Down
164 changes: 164 additions & 0 deletions java/client/src/main/java/glide/api/commands/servermodules/FT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.commands.servermodules;

import static glide.api.models.GlideString.gs;

import glide.api.BaseClient;
import glide.api.GlideClient;
import glide.api.GlideClusterClient;
import glide.api.models.ClusterValue;
import glide.api.models.GlideString;
import glide.api.models.commands.FT.FTCreateOptions;
import glide.api.models.commands.FT.FTCreateOptions.FieldInfo;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;
import lombok.NonNull;

/** Module for vector search commands. */
public class FT {
/**
* Creates an index and initiates a backfill of that index.
*
* @param client The client to execute the command.
* @param indexName The index name.
* @param fields Fields to populate into the index.
* @return <code>OK</code>.
* @example
* <pre>{@code
* // Create an index for vectors of size 2:
* FT.create(client, "my_idx1", new FieldInfo[] {
* new FieldInfo("vec", VectorFieldFlat.builder(DistanceMetric.L2, 2).build())
* }).get();
*
* // Create a 6-dimensional JSON index using the HNSW algorithm:
* FT.create(client, "my_idx2",
* new FieldInfo[] { new FieldInfo("$.vec", "VEC",
* VectorFieldHnsw.builder(DistanceMetric.L2, 6).numberOfEdges(32).build())
* }).get();
* }</pre>
*/
public static CompletableFuture<String> create(
@NonNull BaseClient client, @NonNull String indexName, @NonNull FieldInfo[] fields) {
// Node: bug in meme DB - command fails if cmd is too short even though all mandatory args are
// present
// TODO confirm is it fixed or not and update docs if needed
return create(client, indexName, fields, FTCreateOptions.builder().build());
}

/**
* Creates an index and initiates a backfill of that index.
*
* @param client The client to execute the command.
* @param indexName The index name.
* @param fields Fields to populate into the index.
* @param options Additional parameters for the command - see {@link FTCreateOptions}.
* @return <code>OK</code>.
* @example
* <pre>{@code
* // Create a 6-dimensional JSON index using the HNSW algorithm:
* FT.create(client, "json_idx1",
* new FieldInfo[] { new FieldInfo("$.vec", "VEC",
* VectorFieldHnsw.builder(DistanceMetric.L2, 6).numberOfEdges(32).build())
* },
* FTCreateOptions.builder().indexType(JSON).prefixes(new String[] {"json:"}).build(),
* ).get();
* }</pre>
*/
public static CompletableFuture<String> create(
@NonNull BaseClient client,
@NonNull String indexName,
@NonNull FieldInfo[] fields,
@NonNull FTCreateOptions options) {
return create(client, gs(indexName), fields, options);
}

/**
* Creates an index and initiates a backfill of that index.
*
* @param client The client to execute the command.
* @param indexName The index name.
* @param fields Fields to populate into the index.
* @return <code>OK</code>.
* @example
* <pre>{@code
* // Create an index for vectors of size 2:
* FT.create(client, gs("my_idx1"), new FieldInfo[] {
* new FieldInfo("vec", VectorFieldFlat.builder(DistanceMetric.L2, 2).build())
* }).get();
*
* // Create a 6-dimensional JSON index using the HNSW algorithm:
* FT.create(client, gs("my_idx2"),
* new FieldInfo[] { new FieldInfo(gs("$.vec"), gs("VEC"),
* VectorFieldHnsw.builder(DistanceMetric.L2, 6).numberOfEdges(32).build())
* }).get();
* }</pre>
*/
public static CompletableFuture<String> create(
@NonNull BaseClient client, @NonNull GlideString indexName, @NonNull FieldInfo[] fields) {
// Node: bug in meme DB - command fails if cmd is too short even though all mandatory args are
// present
// TODO confirm is it fixed or not and update docs if needed
return create(client, indexName, fields, FTCreateOptions.builder().build());
}

/**
* Creates an index and initiates a backfill of that index.
*
* @param client The client to execute the command.
* @param indexName The index name.
* @param fields Fields to populate into the index.
* @param options Additional parameters for the command - see {@link FTCreateOptions}.
* @return <code>OK</code>.
* @example
* <pre>{@code
* // Create a 6-dimensional JSON index using the HNSW algorithm:
* FT.create(client, gs("json_idx1"),
* new FieldInfo[] { new FieldInfo(gs("$.vec"), gs("VEC"),
* VectorFieldHnsw.builder(DistanceMetric.L2, 6).numberOfEdges(32).build())
* },
* FTCreateOptions.builder().indexType(JSON).prefixes(new String[] {"json:"}).build(),
* ).get();
* }</pre>
*/
public static CompletableFuture<String> create(
@NonNull BaseClient client,
@NonNull GlideString indexName,
@NonNull FieldInfo[] fields,
@NonNull FTCreateOptions options) {
var args =
Stream.of(
new GlideString[] {gs("FT.CREATE"), indexName},
options.toArgs(),
new GlideString[] {gs("SCHEMA")},
Arrays.stream(fields)
.map(FieldInfo::toArgs)
.flatMap(Arrays::stream)
.toArray(GlideString[]::new))
.flatMap(Arrays::stream)
.toArray(GlideString[]::new);
return executeCommand(client, args, false);
}

/**
* A wrapper for custom command API.
*
* @param client The client to execute the command.
* @param args The command line.
* @param returnsMap - true if command returns a map
*/
@SuppressWarnings("unchecked")
private static <T> CompletableFuture<T> executeCommand(
BaseClient client, GlideString[] args, boolean returnsMap) {
if (client instanceof GlideClient) {
return ((GlideClient) client).customCommand(args).thenApply(r -> (T) r);
} else if (client instanceof GlideClusterClient) {
return ((GlideClusterClient) client)
.customCommand(args)
.thenApply(returnsMap ? ClusterValue::getMultiValue : ClusterValue::getSingleValue)
.thenApply(r -> (T) r);
}
throw new IllegalArgumentException(
"Unknown type of client, should be either `GlideClient` or `GlideClusterClient`");
}
}
Loading

0 comments on commit bbfce44

Please sign in to comment.