{
  "schema_version": 2,
  "id": "develop/clients/lettuce/vecsearch",
  "title": "Index and query vectors",
  "url": "https://redis.io/docs/latest/develop/clients/lettuce/vecsearch/",
  "summary": "Learn how to index and query vector embeddings with Redis",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-10-16T16:44:37+01:00",
  "page_type": "content",
  "content_hash": "d9070186172ba2fad075f601cdaf9b4afe24372732417e8c5f26e15726212b66",
  "sections": [
    {
      "id": "initialize",
      "title": "Initialize",
      "role": "content",
      "text": "If you are using [Maven](https://maven.apache.org/), add the following\ndependencies to your `pom.xml` file:\n\n[code example]\n\nIf you are using [Gradle](https://gradle.org/), add the following\ndependencies to your `build.gradle` file:\n\n[code example]"
    },
    {
      "id": "import-dependencies",
      "title": "Import dependencies",
      "role": "content",
      "text": "Import the following classes in your source file:\n\nFoundational: Import Lettuce, DJL, and embedding model libraries for vector search\n\n**Difficulty:** Beginner\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]"
    },
    {
      "id": "define-a-helper-method",
      "title": "Define a helper method",
      "role": "content",
      "text": "When you store vectors in a hash object, or pass them as query parameters,\nyou must encode the `float` components of the vector\narray as a `byte` string. The helper method `floatArrayToByteArray()`\nshown below does this for you:\n\nFoundational: Convert float arrays to byte arrays for storing vectors in hash objects\n\n**Difficulty:** Beginner\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]"
    },
    {
      "id": "create-an-embedding-model-instance",
      "title": "Create an embedding model instance",
      "role": "content",
      "text": "The example below uses the\n[`all-MiniLM-L6-v2`](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)\nmodel to generate the embeddings. This model generates vectors with 384 dimensions, regardless of the length of the input text, but note that the input is truncated to 256\ntokens (see\n[Word piece tokenization](https://huggingface.co/learn/nlp-course/en/chapter6/6)\nat the [Hugging Face](https://huggingface.co/) docs to learn more about the way tokens\nare related to the original text).\n\nThe [`Predictor`](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/inference/Predictor.html)\nclass implements the model to generate the embeddings. The code below\ncreates an instance of `Predictor` that uses the `all-MiniLM-L6-v2` model:\n\nPractical pattern: Initialize a DJL Predictor with the all-MiniLM-L6-v2 embedding model\n\n**Difficulty:** Beginner\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]"
    },
    {
      "id": "create-the-index",
      "title": "Create the index",
      "role": "content",
      "text": "As noted in [Define a helper method](#define-a-helper-method) above, you must\npass the embeddings to the hash and query commands as a binary string.\n\nLettuce lets you choose a codec for each connection to Redis (see\n[Codecs](https://redis.github.io/lettuce/integration-extension/#codecs)\nin the Lettuce documentation for more information).\n`RedisCodec.of(StringCodec.UTF8, ByteArrayCodec.INSTANCE)` combines two codecs\nso that keys, field names, and index names are `String` objects, while values are\n`byte[]` arrays. The embeddings are binary strings, and you pass text values as\nUTF-8 encoded `byte[]` arrays. However, you will probably find it more convenient\nto use the default `StringCodec` for commands that don't require binary strings.\nIt is therefore helpful to have two connections available, one using the\ncomposed codec and one using `StringCodec`.\n\nThe code below shows how to declare one connection with the\ncomposed codec and another without in the try-with-resources\nblock. You also need two separate instances of `RedisAsyncCommands` to\nuse the two connections:\n\nPractical pattern: Create dual connections with a composed String/byte[] codec and StringCodec for vector operations\n\n**Difficulty:** Intermediate\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\nNext, create the index.\nThe schema in the example below includes three fields:\n\n-   The text content to index\n-   A [tag](https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/tags)\n    field to represent the \"genre\" of the text\n-   The embedding vector generated from the original text content\n\nThe `embedding` field specifies\n[HNSW](https://redis.io/docs/latest/develop/ai/search-and-query/vectors#hnsw-index) \nindexing, the\n[L2](https://redis.io/docs/latest/develop/ai/search-and-query/vectors#distance-metrics)\nvector distance metric, `Float32` values to represent the vector's components,\nand 384 dimensions, as required by the `all-MiniLM-L6-v2` embedding model.\n\nThe `CreateArgs` object specifies hash objects for storage and a\nprefix `doc:` that identifies the hash objects to index.\n\nFoundational: Create a vector search index with HNSW algorithm, L2 distance metric, and 384-dimensional embeddings\n\n**Difficulty:** Intermediate\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]"
    },
    {
      "id": "add-data",
      "title": "Add data",
      "role": "content",
      "text": "You can now supply the data objects, which will be indexed automatically\nwhen you add them with [`hset()`](https://redis.io/docs/latest/commands/hset), as long as\nyou use the `doc:` prefix specified in the index definition.\n\nUse the `predict()` method of the `Predictor` object\nas shown below to create the embedding that represents the `content` field\nand use the `floatArrayToByteArray()` helper method to convert it to a binary string.\nUse the binary string representation when you are\nindexing hash objects, but use an array of `float` for\nJSON objects (see [Differences with JSON objects](#differences-with-json-documents)\nbelow).\n\nYou must use instances of `Map<String, byte[]>` to supply the data to `hset()`\nwhen using the binary connection, so you encode the text values with `getBytes()`. Note\nthat the `predict()` call is in a `try`/`catch` block because it will throw\nexceptions if it can't download the embedding model (you should add code to handle\nthe exceptions in production code).\n\nFoundational: Generate embeddings and store hash documents with vector data using a String/byte[] codec\n\n**Difficulty:** Intermediate\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]"
    },
    {
      "id": "bulk-import-with-himport",
      "title": "Bulk import with HIMPORT",
      "role": "content",
      "text": "From Redis Open Source 8.10, you can also add the documents with the\n[`HIMPORT`](https://redis.io/docs/latest/commands/himport) command family. This creates the same\nhashes as `hset()`, but lets Redis store them as\n[compact hashes](https://redis.io/docs/latest/develop/data-types/hashes#compact-hashes), which use\nless memory when many keys share the same field names. Redis Search indexes\nthese hashes in the same way.\n\nCreate a `HashImport` object with the field names, then create each document\nwith [`himportSet()`](https://redis.io/docs/latest/commands/himport-set), passing only its values,\nin the same order as the field names. Lettuce declares the field names with\n[`HIMPORT PREPARE`](https://redis.io/docs/latest/commands/himport-prepare) the first time you use\nthe `HashImport` object on a connection. Because the binary connection uses\n`String` keys, `HashImport.of()` takes the field names as strings. Issue all the imports before you wait\nfor any reply, so that Lettuce\n[pipelines](https://redis.io/docs/latest/develop/clients/lettuce/transpipe) them instead of\nwaiting for each reply in turn. With the reactive API, wait for the imports\ninside the `try` block, because a `Mono` that you subscribe to after the\n`HashImport` object closes fails:\n\nBulk ingestion: Import hash documents with vector embeddings as compact hashes using a HashImport fieldset and pipelined HIMPORT SET calls\n\n**Difficulty:** Intermediate\n\n**Builds upon:** add_data\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\n`himportSet()` replaces any existing key, so running this code after the\n`hset()` calls leaves you with the same three documents.\n\n> [!NOTE]\n> `HIMPORT` requires Lettuce v7.7.0 or later, and Lettuce marks its support as\n> experimental, so the API might change. Redis Cloud and Redis Software don't\n> support `HIMPORT`."
    },
    {
      "id": "run-a-query",
      "title": "Run a query",
      "role": "content",
      "text": "After you have created the index and added the data, you are ready to run a query.\nTo do this, you must create another embedding vector from your chosen query\ntext. Redis calculates the vector distance between the query vector and each\nembedding vector in the index as it runs the query. You can request the results to be\nsorted to rank them in order of ascending distance.\n\nThe code below creates the query embedding using the `predict()` method, as with\nthe indexing, and passes it as a parameter when the query executes (see\n[Vector search](https://redis.io/docs/latest/develop/ai/search-and-query/query/vector-search)\nfor more information about using query parameters with embeddings).\nThe query is a\n[K nearest neighbors (KNN)](https://redis.io/docs/latest/develop/ai/search-and-query/vectors#knn-vector-search)\nsearch that sorts the results in order of vector distance from the query vector.\n\nSemantic search: Execute a KNN vector search with semantic similarity ranking on hash documents\n\n**Difficulty:** Advanced\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\nAssuming you have added the code from the steps above to your source file,\nit is now ready to run, but note that it may take a while to complete when\nyou run it for the first time (which happens because the model must download the\n`all-MiniLM-L6-v2` model data before it can\ngenerate the embeddings). When you run the code, it outputs the following result text:\n\n[code example]\n\nNote that the results are ordered according to the value of the `distance`\nfield, with the lowest distance indicating the greatest similarity to the query.\nAs you would expect, the result for `doc:1` with the content text\n*\"That is a very happy person\"*\nis the result that is most similar in meaning to the query text\n*\"That is a happy person\"*."
    },
    {
      "id": "differences-with-json-documents",
      "title": "Differences with JSON documents",
      "role": "content",
      "text": "Indexing JSON documents is similar to hash indexing, but there are some\nimportant differences. JSON allows much richer data modeling with nested fields, so\nyou must supply a [path](https://redis.io/docs/latest/develop/data-types/json/path) in the schema\nto identify each field you want to index. However, you can declare a short alias for each\nof these paths (using the `as()` option) to avoid typing it in full for\nevery query. Also, you must specify `CreateArgs.TargetType.JSON` when you create the index.\n\nThe code below shows these differences, but the index is otherwise very similar to\nthe one created previously for hashes:\n\nFoundational: Create a vector search index on JSON documents with JSON paths and field aliases\n\n**Difficulty:** Intermediate\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\nAn important difference with JSON indexing is that the vectors are\nspecified using arrays of `float` instead of binary strings. This means\nyou don't need to use the binary connection, and you can use\n[`Arrays.toString()`](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#toString-float:A-) to convert the `float` array to a suitable JSON string.\n\nUse [`jsonSet()`](https://redis.io/docs/latest/commands/json.set) to add the data\ninstead of [`hset()`](https://redis.io/docs/latest/commands/hset). Use instances\nof `JSONObject` to supply the data instead of `Map`, as you would for\nhash objects.\n\nFoundational: Store JSON documents with vector embeddings as float arrays using JSON.SET\n\n**Difficulty:** Intermediate\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\nThe query is almost identical to the one for the hash documents. This\ndemonstrates how the right choice of aliases for the JSON paths can\nsave you having to write complex queries. An important thing to notice\nis that the vector parameter for the query is still specified as a\nbinary string, even though the data for the `embedding` field of the JSON\nwas specified as an array.\n\nSemantic search: Execute a KNN vector search on JSON documents with semantic similarity ranking\n\n**Difficulty:** Advanced\n\n**Available in:** Java (Asynchronous - Lettuce), Java (Reactive - Lettuce)\n\n##### Java (Asynchronous - Lettuce)\n\n[code example]\n\n##### Java (Reactive - Lettuce)\n\n[code example]\n\n\n\nThe embeddings are generated from the same text as the hash documents, so the\nquery returns the same distances:\n\n[code example]"
    },
    {
      "id": "learn-more",
      "title": "Learn more",
      "role": "related",
      "text": "See\n[Vector search](https://redis.io/docs/latest/develop/ai/search-and-query/query/vector-search)\nfor more information about the indexing options, distance metrics, and query format\nfor vectors."
    }
  ],
  "examples": [
    {
      "id": "initialize-ex0",
      "language": "xml",
      "code": "<dependency>\n    <groupId>io.lettuce</groupId>\n    <artifactId>lettuce-core</artifactId>\n     <!-- Check for the latest version on Maven Central -->\n    <version>7.7.0.RELEASE</version>\n</dependency>\n\n<dependency>\n    <groupId>ai.djl.huggingface</groupId>\n    <artifactId>tokenizers</artifactId>\n    <version>0.33.0</version>\n</dependency>\n\n<dependency>\n    <groupId>ai.djl.pytorch</groupId>\n    <artifactId>pytorch-model-zoo</artifactId>\n    <version>0.33.0</version>\n</dependency>\n\n<dependency>\n    <groupId>ai.djl</groupId>\n    <artifactId>api</artifactId>\n    <version>0.33.0</version>\n</dependency>",
      "section_id": "initialize"
    },
    {
      "id": "initialize-ex1",
      "language": "bash",
      "code": "compileOnly 'io.lettuce:lettuce-core:7.7.0.RELEASE'\ncompileOnly 'ai.djl.huggingface:tokenizers:0.33.0'\ncompileOnly 'ai.djl.pytorch:pytorch-model-zoo:0.33.0'\ncompileOnly 'ai.djl:api:0.33.0'",
      "section_id": "initialize"
    },
    {
      "id": "import-dependencies-ex0",
      "language": "java",
      "code": "// Lettuce client and Redis Search classes.\nimport io.lettuce.core.*;\nimport io.lettuce.core.api.StatefulRedisConnection;\nimport io.lettuce.core.codec.ByteArrayCodec;\nimport io.lettuce.core.codec.RedisCodec;\nimport io.lettuce.core.codec.StringCodec;\nimport io.lettuce.core.api.async.RedisAsyncCommands;\nimport io.lettuce.core.search.arguments.*;\nimport io.lettuce.core.search.SearchReply;\nimport io.lettuce.core.json.JsonParser;\nimport io.lettuce.core.json.JsonObject;\nimport io.lettuce.core.json.JsonPath;\n\n// Standard library classes for data manipulation and\n// asynchronous programming.\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\nimport java.util.concurrent.CompletableFuture;\n\n// DJL classes for model loading and inference.\nimport ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;\nimport ai.djl.inference.Predictor;\nimport ai.djl.repository.zoo.Criteria;\nimport ai.djl.training.util.ProgressBar;",
      "section_id": "import-dependencies"
    },
    {
      "id": "import-dependencies-ex1",
      "language": "java",
      "code": "// Lettuce client and Redis Search classes.\nimport io.lettuce.core.*;\nimport io.lettuce.core.api.StatefulRedisConnection;\nimport io.lettuce.core.codec.ByteArrayCodec;\nimport io.lettuce.core.codec.RedisCodec;\nimport io.lettuce.core.codec.StringCodec;\nimport io.lettuce.core.api.reactive.RedisReactiveCommands;\nimport io.lettuce.core.search.arguments.*;\nimport io.lettuce.core.search.SearchReply;\nimport io.lettuce.core.json.JsonParser;\nimport io.lettuce.core.json.JsonObject;\nimport io.lettuce.core.json.JsonPath;\n\n// Standard library classes for data manipulation and\n// reactive programming.\nimport java.nio.ByteBuffer;\nimport java.nio.ByteOrder;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\nimport reactor.core.publisher.Mono;\n\n// DJL classes for model loading and inference.\nimport ai.djl.huggingface.translator.TextEmbeddingTranslatorFactory;\nimport ai.djl.inference.Predictor;\nimport ai.djl.repository.zoo.Criteria;\nimport ai.djl.training.util.ProgressBar;",
      "section_id": "import-dependencies"
    },
    {
      "id": "define-a-helper-method-ex0",
      "language": "java",
      "code": "private byte[] floatArrayToByteArray(float[] vector) {\n        ByteBuffer buffer = ByteBuffer.allocate(vector.length * 4).order(ByteOrder.LITTLE_ENDIAN);\n        for (float value : vector) {\n            buffer.putFloat(value);\n        }\n        return buffer.array();\n    }",
      "section_id": "define-a-helper-method"
    },
    {
      "id": "define-a-helper-method-ex1",
      "language": "java",
      "code": "private byte[] floatArrayToByteArray(float[] vector) {\n        ByteBuffer buffer = ByteBuffer.allocate(vector.length * 4).order(ByteOrder.LITTLE_ENDIAN);\n        for (float value : vector) {\n            buffer.putFloat(value);\n        }\n        return buffer.array();\n    }",
      "section_id": "define-a-helper-method"
    },
    {
      "id": "create-an-embedding-model-instance-ex0",
      "language": "java",
      "code": "Predictor<String, float[]> predictor = null;\n\n        try {\n            Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)\n                    .optModelUrls(\"djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2\")\n                    .optEngine(\"PyTorch\").optTranslatorFactory(new TextEmbeddingTranslatorFactory())\n                    .optProgress(new ProgressBar()).build();\n\n            predictor = criteria.loadModel().newPredictor();\n        } catch (Exception e) {\n            // ...\n        }",
      "section_id": "create-an-embedding-model-instance"
    },
    {
      "id": "create-an-embedding-model-instance-ex1",
      "language": "java",
      "code": "Predictor<String, float[]> predictor = null;\n\n        try {\n            Criteria<String, float[]> criteria = Criteria.builder().setTypes(String.class, float[].class)\n                    .optModelUrls(\"djl://ai.djl.huggingface.pytorch/sentence-transformers/all-MiniLM-L6-v2\")\n                    .optEngine(\"PyTorch\").optTranslatorFactory(new TextEmbeddingTranslatorFactory())\n                    .optProgress(new ProgressBar()).build();\n\n            predictor = criteria.loadModel().newPredictor();\n        } catch (Exception e) {\n            // ...\n        }",
      "section_id": "create-an-embedding-model-instance"
    },
    {
      "id": "create-the-index-ex0",
      "language": "java",
      "code": "RedisClient redisClient = RedisClient.create(\"redis://localhost:6379\");\n\n        try (StatefulRedisConnection<String, String> connection = redisClient.connect();\n                StatefulRedisConnection<String, byte[]> binConnection = redisClient\n                        .connect(RedisCodec.of(StringCodec.UTF8, ByteArrayCodec.INSTANCE))) {\n            RedisAsyncCommands<String, String> asyncCommands = connection.async();\n            RedisAsyncCommands<String, byte[]> binAsyncCommands = binConnection.async();\n            // ...",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex1",
      "language": "java",
      "code": "RedisClient redisClient = RedisClient.create(\"redis://localhost:6379\");\n\n        try (StatefulRedisConnection<String, String> connection = redisClient.connect();\n                StatefulRedisConnection<String, byte[]> binConnection = redisClient\n                        .connect(RedisCodec.of(StringCodec.UTF8, ByteArrayCodec.INSTANCE))) {\n            RedisReactiveCommands<String, String> reactiveCommands = connection.reactive();\n            RedisReactiveCommands<String, byte[]> binReactiveCommands = binConnection.reactive();\n            // ...",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex2",
      "language": "java",
      "code": "List<FieldArgs<String>> schema = Arrays.asList(TextFieldArgs.<String> builder().name(\"content\").build(),\n                    TagFieldArgs.<String> builder().name(\"genre\").build(),\n                    VectorFieldArgs.<String> builder().name(\"embedding\").hnsw().type(VectorFieldArgs.VectorType.FLOAT32)\n                            .dimensions(384).distanceMetric(VectorFieldArgs.DistanceMetric.L2).build());\n\n            CreateArgs<String, String> createArgs = CreateArgs.<String, String> builder().on(CreateArgs.TargetType.HASH)\n                    .withPrefix(\"doc:\").build();\n\n            CompletableFuture<Void> createIndex = asyncCommands.ftCreate(\"vector_idx\", createArgs, schema)\n                    .thenAccept(System.out::println).toCompletableFuture();",
      "section_id": "create-the-index"
    },
    {
      "id": "create-the-index-ex3",
      "language": "java",
      "code": "List<FieldArgs<String>> schema = Arrays.asList(TextFieldArgs.<String> builder().name(\"content\").build(),\n                    TagFieldArgs.<String> builder().name(\"genre\").build(),\n                    VectorFieldArgs.<String> builder().name(\"embedding\").hnsw().type(VectorFieldArgs.VectorType.FLOAT32)\n                            .dimensions(384).distanceMetric(VectorFieldArgs.DistanceMetric.L2).build());\n\n            CreateArgs<String, String> createArgs = CreateArgs.<String, String> builder().on(CreateArgs.TargetType.HASH)\n                    .withPrefix(\"doc:\").build();\n\n            Mono<Void> createIndex = reactiveCommands.ftCreate(\"vector_idx\", createArgs, schema).doOnNext(result -> {\n                System.out.println(result); // >>> OK\n            }).then();",
      "section_id": "create-the-index"
    },
    {
      "id": "add-data-ex0",
      "language": "java",
      "code": "String sentence1 = \"That is a very happy person\";\n\n            Map<String, byte[]> doc1 = new HashMap<>();\n            doc1.put(\"content\", sentence1.getBytes(StandardCharsets.UTF_8));\n            doc1.put(\"genre\", \"persons\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc1.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence1)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<Long> addDoc1 = binAsyncCommands.hset(\"doc:1\", doc1)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> 3\n                        return result;\n                    }).toCompletableFuture();\n\n            String sentence2 = \"That is a happy dog\";\n\n            Map<String, byte[]> doc2 = new HashMap<>();\n            doc2.put(\"content\", sentence2.getBytes(StandardCharsets.UTF_8));\n            doc2.put(\"genre\", \"pets\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc2.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence2)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<Long> addDoc2 = binAsyncCommands.hset(\"doc:2\", doc2)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> 3\n                        return result;\n                    }).toCompletableFuture();\n\n            String sentence3 = \"Today is a sunny day\";\n\n            Map<String, byte[]> doc3 = new HashMap<>();\n            doc3.put(\"content\", sentence3.getBytes(StandardCharsets.UTF_8));\n            doc3.put(\"genre\", \"weather\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc3.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence3)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<Long> addDoc3 = binAsyncCommands.hset(\"doc:3\", doc3)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> 3\n                        return result;\n                    }).toCompletableFuture();",
      "section_id": "add-data"
    },
    {
      "id": "add-data-ex1",
      "language": "java",
      "code": "String sentence1 = \"That is a very happy person\";\n\n            Map<String, byte[]> doc1 = new HashMap<>();\n            doc1.put(\"content\", sentence1.getBytes(StandardCharsets.UTF_8));\n            doc1.put(\"genre\", \"persons\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc1.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence1)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Long> addDoc1 = binReactiveCommands.hset(\"doc:1\", doc1).doOnNext(result -> {\n                System.out.println(result); // >>> 3\n            });\n\n            String sentence2 = \"That is a happy dog\";\n\n            Map<String, byte[]> doc2 = new HashMap<>();\n            doc2.put(\"content\", sentence2.getBytes(StandardCharsets.UTF_8));\n            doc2.put(\"genre\", \"pets\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc2.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence2)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Long> addDoc2 = binReactiveCommands.hset(\"doc:2\", doc2).doOnNext(result -> {\n                System.out.println(result); // >>> 3\n            });\n\n            String sentence3 = \"Today is a sunny day\";\n\n            Map<String, byte[]> doc3 = new HashMap<>();\n            doc3.put(\"content\", sentence3.getBytes(StandardCharsets.UTF_8));\n            doc3.put(\"genre\", \"weather\".getBytes(StandardCharsets.UTF_8));\n\n            try {\n                doc3.put(\"embedding\", floatArrayToByteArray(predictor.predict(sentence3)));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Long> addDoc3 = binReactiveCommands.hset(\"doc:3\", doc3).doOnNext(result -> {\n                System.out.println(result); // >>> 3\n            });",
      "section_id": "add-data"
    },
    {
      "id": "bulk-import-with-himport-ex0",
      "language": "java",
      "code": "String[][] docData = {\n                    { \"doc:1\", \"That is a very happy person\", \"persons\" },\n                    { \"doc:2\", \"That is a happy dog\", \"pets\" },\n                    { \"doc:3\", \"Today is a sunny day\", \"weather\" } };\n\n            List<RedisFuture<String>> himportDocs = new ArrayList<>();\n\n            try (HashImport<String> fieldset = HashImport.of(\"content\", \"genre\", \"embedding\")) {\n                for (String[] doc : docData) {\n                    byte[] docEmbedding = null;\n\n                    try {\n                        docEmbedding = floatArrayToByteArray(predictor.predict(doc[1]));\n                    } catch (Exception e) {\n                        // ...\n                    }\n\n                    himportDocs.add(binAsyncCommands.himportSet(doc[0], fieldset, doc[1].getBytes(StandardCharsets.UTF_8),\n                            doc[2].getBytes(StandardCharsets.UTF_8), docEmbedding));\n                }\n            }\n\n            CompletableFuture<Void> importDocs = CompletableFuture\n                    .allOf(himportDocs.stream().map(RedisFuture::toCompletableFuture).toArray(CompletableFuture[]::new));",
      "section_id": "bulk-import-with-himport"
    },
    {
      "id": "bulk-import-with-himport-ex1",
      "language": "java",
      "code": "String[][] docData = {\n                    { \"doc:1\", \"That is a very happy person\", \"persons\" },\n                    { \"doc:2\", \"That is a happy dog\", \"pets\" },\n                    { \"doc:3\", \"Today is a sunny day\", \"weather\" } };\n\n            List<Mono<String>> himportDocs = new ArrayList<>();\n\n            try (HashImport<String> fieldset = HashImport.of(\"content\", \"genre\", \"embedding\")) {\n                for (String[] doc : docData) {\n                    byte[] docEmbedding = null;\n\n                    try {\n                        docEmbedding = floatArrayToByteArray(predictor.predict(doc[1]));\n                    } catch (Exception e) {\n                        // ...\n                    }\n\n                    himportDocs.add(binReactiveCommands.himportSet(doc[0], fieldset, doc[1].getBytes(StandardCharsets.UTF_8),\n                            doc[2].getBytes(StandardCharsets.UTF_8), docEmbedding));\n                }\n\n                // Subscribe before the fieldset closes.\n                Mono.when(himportDocs).block();\n            }",
      "section_id": "bulk-import-with-himport"
    },
    {
      "id": "run-a-query-ex0",
      "language": "java",
      "code": "String query = \"That is a happy person\";\n            float[] queryEmbedding = null;\n\n            try {\n                queryEmbedding = predictor.predict(query);\n            } catch (Exception e) {\n                // ...\n            }\n\n            SearchArgs<String, byte[]> searchArgs = SearchArgs.<String, byte[]> builder()\n                    .param(\"vec\", floatArrayToByteArray(queryEmbedding)).returnField(\"content\").returnField(\"vector_distance\")\n                    .sortBy(SortByArgs.<String> builder().attribute(\"vector_distance\").build()).build();\n\n            CompletableFuture<SearchReply<String, byte[]>> hashQuery = binAsyncCommands\n                    .ftSearch(\"vector_idx\", \"*=>[KNN 3 @embedding $vec AS vector_distance]\".getBytes(StandardCharsets.UTF_8),\n                            searchArgs)\n                    .thenApply(result -> {\n                        List<SearchReply.SearchResult<String, byte[]>> results = result.getResults();\n\n                        results.forEach(r -> {\n                            String content = new String(r.getFields().get(\"content\"), StandardCharsets.UTF_8);\n                            String distance = new String(r.getFields().get(\"vector_distance\"), StandardCharsets.UTF_8);\n\n                            System.out.println(\"ID: \" + r.getId() + \", Content: \" + content + \", Distance: \" + distance);\n                        });\n                        // >>> ID: doc:1, Content: That is a very happy person, Distance: 0.114169836044\n                        // >>> ID: doc:2, Content: That is a happy dog, Distance: 0.610845506191\n                        // >>> ID: doc:3, Content: Today is a sunny day, Distance: 1.48624765873\n\n                        return result;\n                    }).toCompletableFuture();",
      "section_id": "run-a-query"
    },
    {
      "id": "run-a-query-ex1",
      "language": "java",
      "code": "String query = \"That is a happy person\";\n            float[] queryEmbedding = null;\n\n            try {\n                queryEmbedding = predictor.predict(query);\n            } catch (Exception e) {\n                // ...\n            }\n\n            SearchArgs<String, byte[]> searchArgs = SearchArgs.<String, byte[]> builder()\n                    .param(\"vec\", floatArrayToByteArray(queryEmbedding)).returnField(\"content\").returnField(\"vector_distance\")\n                    .sortBy(SortByArgs.<String> builder().attribute(\"vector_distance\").build()).build();\n\n            Mono<SearchReply<String, byte[]>> hashQuery = binReactiveCommands\n                    .ftSearch(\"vector_idx\", \"*=>[KNN 3 @embedding $vec AS vector_distance]\".getBytes(StandardCharsets.UTF_8),\n                            searchArgs)\n                    .doOnNext(result -> {\n                        List<SearchReply.SearchResult<String, byte[]>> results = result.getResults();\n\n                        results.forEach(r -> {\n                            String content = new String(r.getFields().get(\"content\"), StandardCharsets.UTF_8);\n                            String distance = new String(r.getFields().get(\"vector_distance\"), StandardCharsets.UTF_8);\n\n                            System.out.println(\"ID: \" + r.getId() + \", Content: \" + content + \", Distance: \" + distance);\n                        });\n                        // >>> ID: doc:1, Content: That is a very happy person, Distance: 0.114169836044\n                        // >>> ID: doc:2, Content: That is a happy dog, Distance: 0.610845506191\n                        // >>> ID: doc:3, Content: Today is a sunny day, Distance: 1.48624765873\n                    });",
      "section_id": "run-a-query"
    },
    {
      "id": "run-a-query-ex2",
      "language": "plaintext",
      "code": "ID: doc:1, Content: That is a very happy person, Distance: 0.114169836044\nID: doc:2, Content: That is a happy dog, Distance: 0.610845506191\nID: doc:3, Content: Today is a sunny day, Distance: 1.48624765873",
      "section_id": "run-a-query"
    },
    {
      "id": "differences-with-json-documents-ex0",
      "language": "java",
      "code": "List<FieldArgs<String>> jsonSchema = Arrays.asList(\n                    TextFieldArgs.<String> builder().name(\"$.content\").as(\"content\").build(),\n                    TagFieldArgs.<String> builder().name(\"$.genre\").as(\"genre\").build(),\n                    VectorFieldArgs.<String> builder().name(\"$.embedding\").as(\"embedding\").hnsw()\n                            .type(VectorFieldArgs.VectorType.FLOAT32).dimensions(384)\n                            .distanceMetric(VectorFieldArgs.DistanceMetric.L2).build());\n\n            CreateArgs<String, String> jsonCreateArgs = CreateArgs.<String, String> builder().on(CreateArgs.TargetType.JSON)\n                    .withPrefix(\"jdoc:\").build();\n\n            CompletableFuture<Void> jsonCreateIndex = asyncCommands.ftCreate(\"vector_json_idx\", jsonCreateArgs, jsonSchema)\n                    .thenAccept(System.out::println).toCompletableFuture();",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex1",
      "language": "java",
      "code": "List<FieldArgs<String>> jsonSchema = Arrays.asList(\n                    TextFieldArgs.<String> builder().name(\"$.content\").as(\"content\").build(),\n                    TagFieldArgs.<String> builder().name(\"$.genre\").as(\"genre\").build(),\n                    VectorFieldArgs.<String> builder().name(\"$.embedding\").as(\"embedding\").hnsw()\n                            .type(VectorFieldArgs.VectorType.FLOAT32).dimensions(384)\n                            .distanceMetric(VectorFieldArgs.DistanceMetric.L2).build());\n\n            CreateArgs<String, String> jsonCreateArgs = CreateArgs.<String, String> builder().on(CreateArgs.TargetType.JSON)\n                    .withPrefix(\"jdoc:\").build();\n\n            Mono<Void> jsonCreateIndex = reactiveCommands.ftCreate(\"vector_json_idx\", jsonCreateArgs, jsonSchema)\n                    .doOnNext(result -> {\n                        System.out.println(result); // >>> OK\n                    }).then();",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex2",
      "language": "java",
      "code": "JsonParser parser = asyncCommands.getJsonParser();\n\n            String jSentence1 = \"That is a very happy person\";\n\n            JsonObject jDoc1 = parser.createJsonObject();\n            jDoc1.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence1 + \"\\\"\"));\n            jDoc1.put(\"genre\", parser.createJsonValue(\"\\\"persons\\\"\"));\n\n            try {\n                jDoc1.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence1))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<String> jsonAddDoc1 = asyncCommands.jsonSet(\"jdoc:1\", JsonPath.ROOT_PATH, jDoc1)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> OK\n                        return result;\n                    }).toCompletableFuture();\n\n            String jSentence2 = \"That is a happy dog\";\n\n            JsonObject jDoc2 = parser.createJsonObject();\n            jDoc2.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence2 + \"\\\"\"));\n            jDoc2.put(\"genre\", parser.createJsonValue(\"\\\"pets\\\"\"));\n\n            try {\n                jDoc2.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence2))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<String> jsonAddDoc2 = asyncCommands.jsonSet(\"jdoc:2\", JsonPath.ROOT_PATH, jDoc2)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> OK\n                        return result;\n                    }).toCompletableFuture();\n\n            String jSentence3 = \"Today is a sunny day\";\n\n            JsonObject jDoc3 = parser.createJsonObject();\n            jDoc3.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence3 + \"\\\"\"));\n            jDoc3.put(\"genre\", parser.createJsonValue(\"\\\"weather\\\"\"));\n\n            try {\n                jDoc3.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence3))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            CompletableFuture<String> jsonAddDoc3 = asyncCommands.jsonSet(\"jdoc:3\", JsonPath.ROOT_PATH, jDoc3)\n                    .thenApply(result -> {\n                        System.out.println(result); // >>> OK\n                        return result;\n                    }).toCompletableFuture();",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex3",
      "language": "java",
      "code": "JsonParser parser = reactiveCommands.getJsonParser();\n\n            String jSentence1 = \"That is a very happy person\";\n            JsonObject jDoc1 = parser.createJsonObject();\n            jDoc1.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence1 + \"\\\"\"));\n            jDoc1.put(\"genre\", parser.createJsonValue(\"\\\"persons\\\"\"));\n\n            try {\n                jDoc1.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence1))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Void> jsonAddDoc1 = reactiveCommands.jsonSet(\"jdoc:1\", JsonPath.ROOT_PATH, jDoc1).doOnNext(result -> {\n                System.out.println(result); // >>> OK\n            }).then();\n\n            String jSentence2 = \"That is a happy dog\";\n            JsonObject jDoc2 = parser.createJsonObject();\n            jDoc2.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence2 + \"\\\"\"));\n            jDoc2.put(\"genre\", parser.createJsonValue(\"\\\"pets\\\"\"));\n\n            try {\n                jDoc2.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence2))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Void> jsonAddDoc2 = reactiveCommands.jsonSet(\"jdoc:2\", JsonPath.ROOT_PATH, jDoc2).doOnNext(result -> {\n                System.out.println(result); // >>> OK\n            }).then();\n\n            String jSentence3 = \"Today is a sunny day\";\n            JsonObject jDoc3 = parser.createJsonObject();\n            jDoc3.put(\"content\", parser.createJsonValue(\"\\\"\" + jSentence3 + \"\\\"\"));\n            jDoc3.put(\"genre\", parser.createJsonValue(\"\\\"weather\\\"\"));\n\n            try {\n                jDoc3.put(\"embedding\", parser.createJsonValue(Arrays.toString(predictor.predict(jSentence3))));\n            } catch (Exception e) {\n                // ...\n            }\n\n            Mono<Void> jsonAddDoc3 = reactiveCommands.jsonSet(\"jdoc:3\", JsonPath.ROOT_PATH, jDoc3).doOnNext(result -> {\n                System.out.println(result); // >>> OK\n            }).then();",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex4",
      "language": "java",
      "code": "String jQuery = \"That is a happy person\";\n            float[] jsonQueryEmbedding = null;\n\n            try {\n                jsonQueryEmbedding = predictor.predict(jQuery);\n            } catch (Exception e) {\n                // ...\n            }\n\n            SearchArgs<String, byte[]> jsonSearchArgs = SearchArgs.<String, byte[]> builder()\n                    .param(\"vec\", floatArrayToByteArray(jsonQueryEmbedding)).returnField(\"content\").returnField(\"vector_distance\")\n                    .sortBy(SortByArgs.<String> builder().attribute(\"vector_distance\").build()).build();\n\n            CompletableFuture<SearchReply<String, byte[]>> jsonQuery = binAsyncCommands\n                    .ftSearch(\"vector_json_idx\", \"*=>[KNN 3 @embedding $vec AS vector_distance]\".getBytes(StandardCharsets.UTF_8),\n                            jsonSearchArgs)\n                    .thenApply(result -> {\n                        List<SearchReply.SearchResult<String, byte[]>> results = result.getResults();\n\n                        results.forEach(r -> {\n                            String content = new String(r.getFields().get(\"content\"), StandardCharsets.UTF_8);\n                            String distance = new String(r.getFields().get(\"vector_distance\"), StandardCharsets.UTF_8);\n\n                            System.out.println(\"ID: \" + r.getId() + \", Content: \" + content + \", Distance: \" + distance);\n                        });\n                        // >>> ID: jdoc:1, Content: That is a very happy person, Distance: 0.114169836044\n                        // >>> ID: jdoc:2, Content: That is a happy dog, Distance: 0.610845506191\n                        // >>> ID: jdoc:3, Content: Today is a sunny day, Distance: 1.48624765873\n\n                        return result;\n                    }).toCompletableFuture();",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex5",
      "language": "java",
      "code": "String jQuery = \"That is a happy person\";\n            float[] jsonQueryEmbedding = null;\n\n            try {\n                jsonQueryEmbedding = predictor.predict(jQuery);\n            } catch (Exception e) {\n                // ...\n            }\n\n            SearchArgs<String, byte[]> jsonSearchArgs = SearchArgs.<String, byte[]> builder()\n                    .param(\"vec\", floatArrayToByteArray(jsonQueryEmbedding)).returnField(\"content\").returnField(\"vector_distance\")\n                    .sortBy(SortByArgs.<String> builder().attribute(\"vector_distance\").build()).build();\n\n            Mono<SearchReply<String, byte[]>> jsonQuery = binReactiveCommands\n                    .ftSearch(\"vector_json_idx\", \"*=>[KNN 3 @embedding $vec AS vector_distance]\".getBytes(StandardCharsets.UTF_8),\n                            jsonSearchArgs)\n                    .doOnNext(result -> {\n                        List<SearchReply.SearchResult<String, byte[]>> results = result.getResults();\n\n                        results.forEach(r -> {\n                            String content = new String(r.getFields().get(\"content\"), StandardCharsets.UTF_8);\n                            String distance = new String(r.getFields().get(\"vector_distance\"), StandardCharsets.UTF_8);\n\n                            System.out.println(\"ID: \" + r.getId() + \", Content: \" + content + \", Distance: \" + distance);\n                        });\n                        // >>> ID: jdoc:1, Content: That is a very happy person, Distance: 0.114169836044\n                        // >>> ID: jdoc:2, Content: That is a happy dog, Distance: 0.610845506191\n                        // >>> ID: jdoc:3, Content: Today is a sunny day, Distance: 1.48624765873\n                    });",
      "section_id": "differences-with-json-documents"
    },
    {
      "id": "differences-with-json-documents-ex6",
      "language": "plaintext",
      "code": "ID: jdoc:1, Content: That is a very happy person, Distance: 0.114169836044\nID: jdoc:2, Content: That is a happy dog, Distance: 0.610845506191\nID: jdoc:3, Content: Today is a sunny day, Distance: 1.48624765873",
      "section_id": "differences-with-json-documents"
    }
  ]
}
