Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Vector search

⚠️ Warning

HelixQL is deprecated in HelixDB v2. Queries are now written with the Rust DSL and dispatched as JSON — see the Querying guide. This section is kept as a reference for legacy HelixQL projects.

For the complete documentation index optimized for AI agents, see llms.txt.

How do I search for similar vectors in HelixDB?

Use SearchV to find vectors similar to your query vector using cosine similarity.

SearchV<Type>(vector, limit)

ℹ️ Note

Currently, Helix only supports using an array of F64 values to represent the vector. We will be adding support for different types such as F32, binary vectors and more in the very near future. Please reach out to us if you need a different vector type.

⚠️ Warning

When using the SDKs or curling the endpoint, the query name must match what is defined in the queries.hx file exactly.

QUERY SearchVector (vector: [F64], limit: I64) =>
    documents <- SearchV<Document>(vector, limit)
    RETURN documents

QUERY InsertVector (vector: [F64], content: String, created_at: Date) =>
    document <- AddV<Document>(vector, { content: content, created_at: created_at })
    RETURN document
V::Document {
    content: String,
    created_at: Date
}

Here’s how to run the query using the SDKs or curl

from datetime import datetime, timezone
from helix.client import Client

client = Client(local=True, port=6969)

vector_data = [0.1, 0.2, 0.3, 0.4]
inserted = client.query("InsertVector", {
    "vector": vector_data,
    "content": "Sample document content",
    "created_at": datetime.now(timezone.utc).isoformat(),
})

result = client.query("SearchVector", {
    "vector": vector_data,
    "limit": 10
})
print(result)
use chrono::Utc;
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let vector_data = vec![0.1, 0.2, 0.3, 0.4];

    let _inserted: serde_json::Value = client.query("InsertVector", &json!({
        "vector": vector_data,
        "content": "Sample document content",
        "created_at": Utc::now().to_rfc3339(),
    })).await?;

    let result: serde_json::Value = client.query("SearchVector", &json!({
        "vector": vector_data,
        "limit": 10,
    })).await?;

    println!("Search results: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    vectorData := []float64{0.1, 0.2, 0.3, 0.4}

    insertPayload := map[string]any{
        "vector":     vectorData,
        "content":    "Sample document content",
        "created_at": time.Now().UTC().Format(time.RFC3339),
    }

    var inserted map[string]any
    if err := client.Query("InsertVector", helix.WithData(insertPayload)).Scan(&inserted); err != nil {
        log.Fatalf("InsertVector failed: %s", err)
    }

    searchPayload := map[string]any{
        "vector": vectorData,
        "limit":  int64(10),
    }

    var result map[string]any
    if err := client.Query("SearchVector", helix.WithData(searchPayload)).Scan(&result); err != nil {
        log.Fatalf("SearchVector failed: %s", err)
    }

    fmt.Printf("Search results: %#v\n", result)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const vectorData = [0.1, 0.2, 0.3, 0.4];

    const inserted = await client.query("InsertVector", {
        vector: vectorData,
        content: "Sample document content",
        created_at: new Date().toISOString(),
    });

    const result = await client.query("SearchVector", {
        vector: vectorData,
        limit: 10,
    });

    console.log("Search results:", result);
}

main().catch((err) => {
    console.error("SearchVector query failed:", err);
});
curl -X POST \
  http://localhost:6969/InsertVector \
  -H 'Content-Type: application/json' \
  -d '{"vector":[0.1,0.2,0.3,0.4],"content":"Sample document content","created_at":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/SearchVector \
  -H 'Content-Type: application/json' \
  -d '{"vector":[0.1,0.2,0.3,0.4],"limit":10}'

Example 2: Vector search with postfiltering

QUERY SearchRecentDocuments (vector: [F64], limit: I64, cutoff_date: Date) =>
    documents <- SearchV<Document>(vector, limit)::WHERE(_::{created_at}::GTE(cutoff_date))
    RETURN documents

QUERY InsertVector (vector: [F64], content: String, created_at: Date) =>
    document <- AddV<Document>(vector, { content: content, created_at: created_at })
    RETURN document
V::Document {
    content: String,
    created_at: Date
}

Here’s how to run the query using the SDKs or curl

from datetime import datetime, timezone, timedelta
from helix.client import Client

client = Client(local=True, port=6969)

vector_data = [0.12, 0.34, 0.56, 0.78]

recent_date = datetime.now(timezone.utc).isoformat()
old_date = (datetime.now(timezone.utc) - timedelta(days=45)).isoformat()

client.query("InsertVector", {
    "vector": vector_data,
    "content": "Recent document content",
    "created_at": recent_date,
})

client.query("InsertVector", {
    "vector": [0.15, 0.35, 0.55, 0.75],
    "content": "Old document content", 
    "created_at": old_date,
})

cutoff_date = (datetime.now(timezone.utc) - timedelta(days=30)).isoformat()

result = client.query("SearchRecentDocuments", {
    "vector": vector_data,
    "limit": 5,
    "cutoff_date": cutoff_date,
})

print(result)
use chrono::{Duration, Utc};
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let vector_data = vec![0.12, 0.34, 0.56, 0.78];

    let recent_date = Utc::now().to_rfc3339();
    let old_date = (Utc::now() - Duration::days(45)).to_rfc3339();

    let _recent: serde_json::Value = client.query("InsertVector", &json!({
        "vector": vector_data,
        "content": "Recent document content",
        "created_at": recent_date,
    })).await?;

    let _old: serde_json::Value = client.query("InsertVector", &json!({
        "vector": [0.15, 0.35, 0.55, 0.75],
        "content": "Old document content",
        "created_at": old_date,
    })).await?;

    let cutoff_date = (Utc::now() - Duration::days(30)).to_rfc3339();

    let result: serde_json::Value = client.query("SearchRecentDocuments", &json!({
        "vector": vector_data,
        "limit": 5,
        "cutoff_date": cutoff_date,
    })).await?;

    println!("Filtered search results: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    vectorData := []float64{0.12, 0.34, 0.56, 0.78}

    recentDate := time.Now().UTC().Format(time.RFC3339)
    oldDate := time.Now().UTC().AddDate(0, 0, -45).Format(time.RFC3339)

    recentPayload := map[string]any{
        "vector":     vectorData,
        "content":    "Recent document content",
        "created_at": recentDate,
    }
    var recent map[string]any
    if err := client.Query("InsertVector", helix.WithData(recentPayload)).Scan(&recent); err != nil {
        log.Fatalf("InsertVector (recent) failed: %s", err)
    }

    oldPayload := map[string]any{
        "vector":     []float64{0.15, 0.35, 0.55, 0.75},
        "content":    "Old document content",
        "created_at": oldDate,
    }
    var old map[string]any
    if err := client.Query("InsertVector", helix.WithData(oldPayload)).Scan(&old); err != nil {
        log.Fatalf("InsertVector (old) failed: %s", err)
    }

    cutoffDate := time.Now().UTC().AddDate(0, 0, -30).Format(time.RFC3339)

    searchPayload := map[string]any{
        "vector":      vectorData,
        "limit":       int64(5),
        "cutoff_date": cutoffDate,
    }

    var result map[string]any
    if err := client.Query("SearchRecentDocuments", helix.WithData(searchPayload)).Scan(&result); err != nil {
        log.Fatalf("SearchRecentDocuments failed: %s", err)
    }

    fmt.Printf("Filtered search results: %#v\n", result)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const vectorData = [0.12, 0.34, 0.56, 0.78];

    const recentDate = new Date().toISOString();
    const oldDate = new Date(Date.now() - 45 * 24 * 60 * 60 * 1000).toISOString();

    await client.query("InsertVector", {
        vector: vectorData,
        content: "Recent document content",
        created_at: recentDate,
    });

    await client.query("InsertVector", {
        vector: [0.15, 0.35, 0.55, 0.75],
        content: "Old document content",
        created_at: oldDate,
    });

    const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();

    const result = await client.query("SearchRecentDocuments", {
        vector: vectorData,
        limit: 5,
        cutoff_date: cutoffDate,
    });

    console.log("Filtered search results:", result);
}

main().catch((err) => {
    console.error("SearchRecentDocuments query failed:", err);
});
curl -X POST \
  http://localhost:6969/InsertVector \
  -H 'Content-Type: application/json' \
  -d '{"vector":[0.12,0.34,0.56,0.78],"content":"Recent document content","created_at":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/InsertVector \
  -H 'Content-Type: application/json' \
  -d '{"vector":[0.15,0.35,0.55,0.75],"content":"Old document content","created_at":"'"$(date -u -d '45 days ago' +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/SearchRecentDocuments \
  -H 'Content-Type: application/json' \
  -d '{"vector":[0.12,0.34,0.56,0.78],"limit":5,"cutoff_date":"'"$(date -u -d '30 days ago' +"%Y-%m-%dT%H:%M:%SZ")"'"}'

Example 3: Using the built in Embed function

You can also use the built in Embed function to search with text directly without sending in the array of floats. It uses the embedding model defined in your config.hx.json file.

⚠️ Warning

All vectors in a vector type must have the same dimensions. If you change your embedding model (e.g., switching from text-embedding-ada-002 to a different model), the new vectors will have different dimensions and will cause an error. Ensure you use the same embedding model consistently for all vectors.

QUERY SearchWithText (text: String, limit: I64) =>
    documents <- SearchV<Document>(Embed(text), limit)
    RETURN documents

QUERY InsertTextAsVector (content: String, created_at: Date) =>
    document <- AddV<Document>(Embed(content), { content: content, created_at: created_at })
    RETURN document
V::Document {
    content: String,
    created_at: Date
}
OPENAI_API_KEY=your_api_key

Here’s how to run the query using the SDKs or curl

from datetime import datetime, timezone
from helix.client import Client

client = Client(local=True, port=6969)

sample_texts = [
    "Introduction to machine learning algorithms",
    "Deep neural networks and AI",
    "Natural language processing techniques"
]

for text in sample_texts:
    client.query("InsertTextAsVector", {
        "content": text,
        "created_at": datetime.now(timezone.utc).isoformat(),
    })

result = client.query("SearchWithText", {
    "text": "machine learning algorithms",
    "limit": 10,
})

print(result)
use chrono::Utc;
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let sample_texts = vec![
        "Introduction to machine learning algorithms",
        "Deep neural networks and AI",
        "Natural language processing techniques"
    ];

    for text in &sample_texts {
        let _inserted: serde_json::Value = client.query("InsertTextAsVector", &json!({
            "content": text,
            "created_at": Utc::now().to_rfc3339(),
        })).await?;
    }

    let result: serde_json::Value = client.query("SearchWithText", &json!({
        "text": "machine learning algorithms",
        "limit": 10,
    })).await?;

    println!("Text search results: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    sampleTexts := []string{
        "Introduction to machine learning algorithms",
        "Deep neural networks and AI",
        "Natural language processing techniques",
    }

    for _, text := range sampleTexts {
        insertPayload := map[string]any{
            "content":    text,
            "created_at": time.Now().UTC().Format(time.RFC3339),
        }

        var inserted map[string]any
        if err := client.Query("InsertTextAsVector", helix.WithData(insertPayload)).Scan(&inserted); err != nil {
            log.Fatalf("InsertTextAsVector failed: %s", err)
        }
    }

    searchPayload := map[string]any{
        "text":  "machine learning algorithms",
        "limit": int64(10),
    }

    var result map[string]any
    if err := client.Query("SearchWithText", helix.WithData(searchPayload)).Scan(&result); err != nil {
        log.Fatalf("SearchWithText failed: %s", err)
    }

    fmt.Printf("Text search results: %#v\n", result)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const sampleTexts = [
        "Introduction to machine learning algorithms",
        "Deep neural networks and AI",
        "Natural language processing techniques"
    ];

    for (const text of sampleTexts) {
        await client.query("InsertTextAsVector", {
            content: text,
            created_at: new Date().toISOString(),
        });
    }

    const result = await client.query("SearchWithText", {
        text: "machine learning algorithms",
        limit: 10,
    });

    console.log("Text search results:", result);
}

main().catch((err) => {
    console.error("SearchWithText query failed:", err);
});
curl -X POST \
  http://localhost:6969/InsertTextAsVector \
  -H 'Content-Type: application/json' \
  -d '{"content":"Introduction to machine learning algorithms","created_at":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/InsertTextAsVector \
  -H 'Content-Type: application/json' \
  -d '{"content":"Deep neural networks and AI","created_at":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/InsertTextAsVector \
  -H 'Content-Type: application/json' \
  -d '{"content":"Natural language processing techniques","created_at":"'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'

curl -X POST \
  http://localhost:6969/SearchWithText \
  -H 'Content-Type: application/json' \
  -d '{"text":"machine learning algorithms","limit":10}'