Skip to content

Ask the HotKV docs

Answers come only from these docs and can be wrong; check the linked pages before you rely on them.

Vector search

Last updated
All Cloud plansOn-Premise: no license needed

Vector search finds the stored vectors closest to a query vector. Put the embeddings of your documents, products, or images into an index, then ask for the k nearest neighbors of a query embedding: that is the retrieval step of semantic search, recommendations (“more like this”), duplicate detection, and retrieval-augmented generation (RAG).

HotKV’s VSIM.* commands do this with HNSW-indexed approximate nearest neighbor search, using cosine, Euclidean (L2) or inner-product distance. They are part of every HotKV server and every HotKV Cloud plan, with no license needed. The AI features (semantic cache, agent memory, the RAG pipeline) work with the same vector indexes.

An index has a name, a fixed number of dimensions, and a distance metric. Each item in it is a name (the “key” in the command syntax) with one vector. Indexes and their items live next to the keyspace, not in it: an index is not a key, DEL and EXPIRE do not apply to it, and an item name does not have to be an existing key. Using your object’s key as the item name (for example product:1) is still a good habit, because it lets you fetch the object after a search and filter by tags.

VSIM.CREATEINDEX creates an index with its dimensions (1 to 65536). The metric is cosine unless you pass METRIC L2 or METRIC IP.

127.0.0.1:6379> VSIM.CREATEINDEX docs 3
OK
127.0.0.1:6379> VSIM.SET docs a 1 0 0
(integer) 1
127.0.0.1:6379> VSIM.SET docs b 0 1 0
(integer) 1
127.0.0.1:6379> VSIM.SET docs c 1 1 0
(integer) 1
127.0.0.1:6379> VSIM.SET docs c 1 1 0
(integer) 0
127.0.0.1:6379> VSIM.SEARCH docs 2 1 0 0
1) "a"
2) "0"
3) "c"
4) "0.29289323"
127.0.0.1:6379> VSIM.GET docs c
1) "0.70710677"
2) "0.70710677"
3) "0"
127.0.0.1:6379> VSIM.SET docs d 1 0
(error) ERR expected 3 dimensions, got 2
127.0.0.1:6379> VSIM.DEL docs b
(integer) 1
127.0.0.1:6379> VSIM.INFO
1) "docs"
127.0.0.1:6379> VSIM.DROPINDEX docs
OK
  • VSIM.SET takes exactly as many numbers as the index has dimensions. It replies 1 for a new item and 0 when it replaced an existing item’s vector.
  • VSIM.SEARCH takes k, then the query vector, and returns up to k items, nearest first, each followed by its distance.
  • VSIM.GET returns an item’s stored vector (nil if there is none). A cosine index stores vectors scaled to unit length, so you get back the normalized vector, as c shows above.
  • VSIM.DEL removes an item, and VSIM.DROPINDEX removes the whole index.
  • VSIM.INFO without arguments lists the indexes; with an index name it reports its dimensions, metric, number of vectors, index parameters and memory use.

Vector values are stored as 32-bit floats and must be finite numbers.

Lower is always closer.

Metric Distance returned Range
COSINE (default) 1 minus the cosine similarity 0 (same direction) to 2 (opposite)
L2 Squared Euclidean distance 0 and up
IP The negative dot product Any number; more negative is closer

Use the metric your embedding model was trained for. Most text embedding models are meant for cosine; if your vectors are already unit length, cosine and inner product rank results the same way.

Search is approximate: on large indexes it may occasionally miss a true nearest neighbor in exchange for answering quickly. VSIM.CREATEINDEX accepts M, EF_CONSTRUCTION and EF_SEARCH to tune the index, and VSIM.SEARCH takes EF <n> to trade speed for recall on a single query: a higher EF examines more candidates, finding the true neighbors more reliably but taking longer. VSIM.INFO <index> shows the values an index uses. The defaults suit most workloads.

VSIM.SEARCH ... FILTER tag [tag ...] restricts the search to items whose name is a key carrying all of the given tags. Put FILTER after the vector, and EF (if any) after the tags.

127.0.0.1:6379> VSIM.CREATEINDEX products 3
OK
127.0.0.1:6379> HSET product:1 name "Trail runner"
(integer) 1
127.0.0.1:6379> HSET product:2 name "Rain jacket"
(integer) 1
127.0.0.1:6379> TAG.SET product:1 shoes outdoor
(integer) 2
127.0.0.1:6379> TAG.SET product:2 jackets outdoor
(integer) 2
127.0.0.1:6379> VSIM.SET products product:1 1 1 0
(integer) 1
127.0.0.1:6379> VSIM.SET products product:2 1 0 0
(integer) 1
127.0.0.1:6379> VSIM.SEARCH products 5 1 0 0
1) "product:2"
2) "0"
3) "product:1"
4) "0.29289323"
127.0.0.1:6379> VSIM.SEARCH products 5 1 0 0 FILTER shoes
1) "product:1"
2) "0.29289323"
127.0.0.1:6379> VSIM.SEARCH products 5 1 0 0 FILTER outdoor jackets
1) "product:2"
2) "0"

The jacket is the closer match, but with FILTER shoes only the shoe is considered. Tags can only be set on keys that exist, which is why each product has a hash here.

  • Indexes and their vectors are saved in snapshots and the AOF and come back on restart; replicas hold the same indexes as their primary.
  • FLUSHALL removes all indexes; FLUSHDB does not touch them.
  • In a cluster, an index lives on the node that owns its name’s hash slot, and commands for it are redirected like key commands. A filtered search sees only the tags held on that node, so keep tagged keys and their index on the same node (with a common hash tag) when you filter in a cluster. VSIM.INFO without arguments lists only the node’s own indexes.
Cloud: Performance and ScaleOn-Premise: vsim-persist license

VSIM.SAVE <name> <payload> stores a payload you supply (for example an export of your vectors in your own format) as a named file on the server, and replies with the number of bytes written. VSIM.LOAD <name> returns it (nil if there is none), VSIM.LIST names the saved payloads, and VSIM.DROP <name> deletes one (1 or 0). These commands do not save or restore an index by themselves: indexes are already persisted as described above.

They need the vsim-persist license feature and enabled = true under [vsim_persist] in the configuration; files go to the directory set by dir in that section (vsim_snapshots by default). In a cluster, each node keeps its own files. See the AI features guide for licensing details.

VSIM.* is HotKV’s own command family. HotKV does not implement the vector set commands of Redis 8 (VADD, VSIM, VREM, VEMB and the rest), and Redis’s single VSIM command is unrelated to HotKV’s VSIM.SEARCH. Applications that use Redis vector sets or the RediSearch vector fields need to switch to these commands.

Command What it does
VSIM.CREATEINDEX Create an index
VSIM.DROPINDEX Delete an index
VSIM.SET Add or replace an item’s vector
VSIM.GET Read an item’s vector
VSIM.DEL Remove an item
VSIM.SEARCH Nearest neighbors, optionally filtered by tags
VSIM.INFO List indexes, or describe one
VSIM.SAVE / VSIM.LOAD Store or fetch a named payload file
VSIM.LIST / VSIM.DROP List or delete payload files
import hotkv
client = hotkv.HotKV(host="localhost", port=6379, decode_responses=True)
client.vsim_createindex("docs", 3, metric="cosine")
client.vsim_set("docs", "a", [1.0, 0.0, 0.0])
client.vsim_set("docs", "c", [1.0, 1.0, 0.0])
for name, distance in client.vsim_search("docs", 2, [1.0, 0.0, 0.0]):
print(name, distance)
# Only among keys tagged "shoes":
client.vsim_search("products", 5, [1.0, 0.0, 0.0], filter_tags=["shoes"])
client.close()