Whatever message this page gives is out now! Go check it out!

Work with vector stores in ColdFusion

Last update:
May 18, 2026
Implement RAG-style retrieval in ColdFusion using vector stores. Store embeddings, search by similarity, and integrate results into AI workflows with cfscript.
Vector stores help you find text by meaning, not just by matching keywords. You add your content once, and later you can search it using natural questions to get the most relevant results—even if the words don’t exactly match.
how vector stores fit into indexing and query workflows, how to configure clients, and common use cases with full cfscript samples. It covers the core operations; add, addAll, search, delete, deleteAll, and deleteCollection, using simple, reproducible examples.

Review the indexing and query workflow

Vector stores follow a two-phase pattern. Indexing: you turn content into embeddings and store those vectors (with optional text and metadata). Query: you turn a question into an embedding (or pass a vector directly) and retrieve the nearest neighbors by similarity score.
That split matters for design: write path (chunk, embed, store) can run offline or in a job; read path (embed query, search, return text for the app or an LLM) usually runs on each request.

Pre-requisites

  • ColdFusion 2025.0.08
  • Endpoint URLs and credentials for your provider when you are not using the in-memory store.
  • VectorStore() with no arguments uses the default local embedding model (all_minilm, 384 dimensions). You can override the default by configuring an embeddingModel when creating the client. ColdFusion generates embeddings automatically from text; you do not need to pass embeddings explicitly.
  • For hosted providers: collection settings such as dimension and metricType that match your embedding model (see your provider’s limits)

When to use a vector store

Goal
Why vectors help
Answer questions from your own content (RAG)
Retrieve passages that are semantically related to the user’s question, then send them to a chat or completion model.
“Similar items” in a catalog or knowledge base
Compare the meaning of titles and descriptions, not only keywords.
Scoped search (tenant, locale, product line)
Combine similarity search with metadata filters so results stay inside the right partition.
Syncing content from a CMS or ticket system
Upsert by stable ids and delete by filter when content is removed or archived.
Large documents
Chunk text, embed each chunk, and batch writes to stay within message size and memory limits.
The examples below use in-memory clients, where you can run them without external services.

Start with the in-memory vector store

For local tests and prototypes, call VectorStore() with no arguments. That initializes an in-memory vector store with the default local embedding model (all_minilm, 384 dimensions). You can pass documents with text only; you do not need to pass an embedding unless you want to override the model output (if you pass an embedding, it takes precedence over the configured embedding model).
<cfscript>
    try {
    vectorstoreclient = VectorStore(); // In-memory; default local embedding model all_minilm (384 dimensions)
    docs = [
        {
            "text": "ColdFusion is a rapid application development platform.",
            "metadata": { "category": "tech" }
        },
        {
            "text": "Python is popular for data science.",            
            "metadata": { "category": "data" }
        }
    ];
        addedIds = vectorstoreclient.addAll(docs);
        writeDump(addedIds);
    } 
    catch (any e) {
        writeOutput("Error initializing VectorStore client:<br><br>");
        writeDump(e.detail);
    }
</cfscript>
The same add‑and‑search pattern also works with external vector databases and retrieval‑augmented generation (RAG) workflows. ColdFusion provides a provider‑agnostic API, so you can start in memory and later move to hosted stores such as Milvus, Pinecone, Qdrant, or Chroma without changing your core application logic.

Add a few documents

Once the client exists, you can index content. Indexing here means: pass text (and optional metadata), and let the client embed and store it. You can add one document with add or several with addAll.
Each struct you pass is one logical document. text is required for the usual path. metadata is optional but worth using early (for example a category key) because it unlocks filtered search later. id is optional; if you skip it, the server can assign ids for you. You do not need to pass a raw embedding while the default embedding model is active—ColdFusion derives embeddings from text.
The sample first adds a single document, then builds a small array and passes it to addAll. writeDump shows the returned id(s) so you can confirm the round trip.
Example
Using VectorStore() without parameters
<cfscript>
    try{
        vectorstoreclient = VectorStore();
        // Single document
        oneId = vectorstoreclient.add({
            "text": "ColdFusion is a rapid application development platform.",
            "metadata": { "category": "tech", "source": "intro" }
        });
        writeOutput("<h4>add() result (single id)</h4>");
        writeDump(oneId);

        // Multiple documents
        docs = [
            {
                "text": "Vector databases support similarity search over embeddings.",
                "metadata": { "category": "database" }
            },
            {
                // "id": "optional-fixed-id",  // optional
                "text": "Python is widely used for data science and machine learning.",
                "metadata": { "category": "data" }
            }
        ];
        addedIds = vectorstoreclient.addAll(docs);
        writeOutput("<h4>addAll() result (array of ids)</h4>");
        writeDump(addedIds);
    } 
    catch (any e) {
        writeOutput("Error initializing VectorStore client:<br><br>");
    }
</cfscript>
Using VectorStore() with parameters
<cfscript>
    try{
        vs = VectorStore({
            provider: "inmemory",
            embeddingModel: {
                "provider": "openai",
                "modelName": "text-embedding-3-small",
                "apiKey": "#application.apiKey#"
            }
        });
    vs.add({
        "id": "kb-article-10042",
        "text": "Return policy: items within 30 days with receipt.",
        "metadata": { "docType": "policy", "locale": "en-US" }
    });

    doc=vs.add({
        "text": "Shipping is free over $50.",
        "metadata": { "docType": "marketing", "locale": "en-US" }
    });

    writeDump(doc)
    
    }
    
    catch (any e) {
        writeOutput("Error initializing VectorStore client:<br><br> ");
        writedump(e.detail);
    }
</cfscript>

Search

Search is where you ask for semantically similar rows. The client turns your query text into a vector the same way it embedded your documents, then compares it to stored vectors and returns the best matches.
You control how many results you want with topK and how strict the match must be with minScore. Thresholds depend on your model and data; start with a modest minScore and adjust after you inspect score on each hit. Returned rows usually include score, text, and metadata (see your function reference for the exact struct shape).
The script below is self-contained: it creates a fresh in-memory client, indexes two short documents, then runs one search. You can paste it into a test page as a single block.
Without parameters
<cfscript>
    try{
        vectorstoreclient = VectorStore();
        // Single document
        oneId = vectorstoreclient.add({
            "text": "ColdFusion is a rapid application development platform.",
            "metadata": { "category": "tech", "source": "intro" }
        });
        writeOutput("<h4>add() result (single id)</h4>");
        writeDump(oneId);

        // Multiple documents
        docs = [
            {
                "text": "Vector databases support similarity search over embeddings.",
                "metadata": { "category": "database" }
            },
            {
                // "id": "optional-fixed-id",  // optional
                "text": "Python is widely used for data science and machine learning.",
                "metadata": { "category": "data" }
            }
        ];
        addedIds = vectorstoreclient.addAll(docs);
        writeOutput("<h4>addAll() result (array of ids)</h4>");
        writeDump(addedIds);
    } 
    catch (any e) {
        writeOutput("Error initializing VectorStore client:<br><br>");
    }
</cfscript>
With parameters
<cfscript>
    try{
        vectorstoreclient = VectorStore({
            provider: "inmemory",
            embeddingModel: {
                "provider": "openai",
                "modelName": "text-embedding-3-small",
                "apiKey": "#application.apiKey#"
            }
        });
        // Single document
        oneId = vectorstoreclient.add({
            "text": "ColdFusion is a rapid application development platform.",
            "metadata": { "category": "tech", "source": "intro" }
        });
        writeOutput("<h4>add() result (single id)</h4>");
        writeDump(oneId);

        // Multiple documents
        docs = [
            {
                "text": "Vector databases support similarity search over embeddings.",
                "metadata": { "category": "database" }
            },
            {
                // "id": "optional-fixed-id",  // optional
                "text": "Python is widely used for data science and machine learning.",
                "metadata": { "category": "data" }
            }
        ];
        addedIds = vectorstoreclient.addAll(docs);
        writeOutput("<h4>addAll() result (array of ids)</h4>");
        writeDump(addedIds);
    } 
    catch (any e) {
        writeOutput("Error initializing VectorStore client:<br><br>");
    }
</cfscript>

In-memory with a remote embedding model

Use provider: "inmemory" when you want the same process-local store but a specific embeddingModel (for example OpenAI).
Note: Pull third-party models in Ollama before you point modelName at them.
<cfscript>
    try {
        vectorstoreclient = VectorStore(); // Initializes inmemory vectorstore with all_minilm(local embedding model with 384 dimension)
        docs = [
            {
                "text": "ColdFusion is a rapid application development platform.",
                //"embedding": [0.1, 0.2, 0.9], Not required to mention embedding explicitly as we have local embedding model configured by default but if you specify this is prioritized.
                "metadata": {"category": "tech"}
            },
            { 
                // "id": "2", Id is optional
                "text": "Python is popular for Data Science.",
                // "embedding": [0.8, 0.1, 0.1],
                "metadata": {"category": "data"}
            }
        ];
        // Add documents and get their IDs back
        addedIds = vectorstoreclient.addAll(docs);
        writeDump(addedIds);
    } catch (any e) {
        writeOutput("Error initializing simple VectorStore client:<br><br> ");
        writedump(e.detail);
    }

    try {
        vs = VectorStore({
            provider: "inmemory",
            embeddingModel: {
                "provider": "openai",
                "modelName": "text-embedding-3-small",
                "apiKey": "#application.apiKey#"
            }
            /*
                For openai embeddingmodel
                embeddingModel: {
                    "provider": "ollama",
                    "modelName": "qwen3-embedding:8b" // You need to pull the model in ollama, or else you can use openai
                }
            */
        });

        writeDump(vs.add({
            "text": "Only text is required"
        }));
    } catch (any e) {
        writeOutput("<hr>Error initializing alternate VectorStore client:<br><br> ");
        writedump(e.detail);
    }
</cfscript>

Create a client for a hosted provider

Pass a struct that includes `provider` and your connection details. The example below uses Milvus. Other providers follow the same pattern with different required fields.
milvusClient = VectorStore({ 
    provider: "milvus", 
    url: "https://your-host.example.com:19530", 
    apiKey: "your-api-key" 
}); 
Set connection options (timeouts, retries, keep-alive) and collection options (dimension (mandatory), metric, index type, field names) on the struct. If a collection is missing, it is created for you so you can focus on data operations.

Register configs (Administrator / Admin API)

Vector store definitions are usually registered with the Vector Store Admin API (after administrator login).
For example:
<cfscript>
    vectorStoreAPI = createObject("component", "CFIDE.adminapi.vectorstore"); 
    vectorStoreAPI.addVectorStoreConfig("myMilvus", configStruct); 
    retrieved = vectorStoreAPI.getVectorStoreConfig("myMilvus");
</cfscript>

Use cases and code samples

Use case 1: Support knowledge base (RAG-style retrieval)
Scenario: You store short FAQ and help article snippets. When a user asks a question, you search for the closest chunks and pass the returned text to your AI service as context (your app is responsible for calling the LLM with that context).
<cfscript>
    try {
    // Production: use GetVectorStoreClient with provider milvus, pinecone, qdrant, or chroma plus url, apiKey, collectionName, dimension, and embeddingModel.
    vectorstoreclient = VectorStore({
        "provider": "milvus",
        "url" = "milvus_endpoint_url",
        "databaseName": "default",
        "collectionName": "support_kb",
        "dimension": 384,
        "indexType": "HNSW",
        "metricType": "COSINE",
        "embeddingModel": {
            "provider": "ollama",
            "modelName": "all-minilm:latest",
            "baseUrl": "your_endpoint_url",
            "maxRetries": 3
        }
    });

    faqChunks = [
        {
            "id": "faq-reset-1",
            "text": "To reset your password, open the login page and select Forgot password. Enter your email and follow the link within 24 hours.",
            "metadata": { "articleId": "KB-1001", "department": "accounts", "source": "faq" }
        },
        {
            "id": "faq-billing-1",
            "text": "Invoices are generated on the first of each month. You can download PDF copies from Billing > Invoices.",
            "metadata": { "articleId": "KB-2040", "department": "billing", "source": "faq" }
        },
        {
            "id": "faq-api-1",
            "text": "API rate limits default to 1000 requests per minute per API key. Contact sales for higher tiers.",
            "metadata": { "articleId": "KB-3100", "department": "developer", "source": "article" }
        }
    ];

    addedIds = vectorstoreclient.addAll(faqChunks);
    writeDump(addedIds);

    userQuestion = "I forgot my login password and need a new one";

    hits = vectorstoreclient.search({
        "text": userQuestion,
        "topK": 3,
        "minScore": 0.45,
        "filter": {
            "source": "faq",
            "$or": [
                { "department": "accounts" },
                { "department": "developer" }
            ]
        }
    });

    contextBlock = "";
    for (i = 1; i <= arrayLen(hits); i++) {
        contextBlock &= hits[i].text & chr(10) & chr(10);
    }
    // Pass contextBlock to your ColdFusion AI service or HTTP call to the LLM as retrieval context.
    writeDump(hits);
    } catch (any e) {
        writeOutput("Knowledge base vector store error:<br><br>");
        writeDump(e.detail);
    }
</cfscript>
Use case 2: E-commerce “similar products”
Scenario: Shoppers view a product page; you show semantically related products in the same category, excluding the current SKU.
<cfscript>
    try {
    vectorstoreclient = VectorStore(); // Default all_minilm (384); prototype only — not for production

    products = [
        {
            "id": "sku-501",
            "text": "Trail runner shoes waterproof breathable size 7–12 black",
            "metadata": { "sku": "sku-501", "category": "footwear", "inStock": true }
        },
        {
            "id": "sku-502",
            "text": "Lightweight hiking boots leather ankle support waterproof",
            "metadata": { "sku": "sku-502", "category": "footwear", "inStock": true }
        },
        {
            "id": "sku-900",
            "text": "Stainless steel water bottle 32oz insulated",
            "metadata": { "sku": "sku-900", "category": "accessories", "inStock": false }
        }
    ];

    writeDump(vectorstoreclient.addAll(products));

    currentSku = "sku-501";
    seedText = "Trail runner shoes waterproof breathable";

    similar = vectorstoreclient.search({
        "text": seedText,
        "topK": 5,
        "minScore": 0.35,
        "filter": {
            "category": "footwear",
            "inStock": true,
            "sku": { "$ne": currentSku }
        }
    });

    writeDump(similar);
    } catch (any e) {
        writeOutput("Catalog vector store error:<br><br>");
        writeDump(e.detail);
    }
</cfscript>
Use case 3: Locale and time-based news or blog search
Scenario: Readers search a corpus where each item has locale and publishedYear. Filters keep results in the right language and recency band.
<cfscript>
    try{
        vectorStoreClient=vectorStore({
            provider: "inmemory",
            embeddingModel: {
                "provider": "openai",
                "modelName": "text-embedding-3-small",
                "apiKey": "#application.apiKey#"
            }
        })

        articles = [
            {
                "text": "ColdFusion 2025.0.08 adds vector stores for AI workloads.",
                "metadata": { "locale": "en-US", "publishedYear": 2026, "section": "product" }
            },
            {
                "text": "Las tiendas vectoriales permiten búsqueda semántica en español.",
                "metadata": { "locale": "es-ES", "publishedYear": 2026, "section": "product" }
            },
            {
                "text": "Legacy announcement from 2020 about earlier CF releases.",
                "metadata": { "locale": "en-US", "publishedYear": 2020, "section": "archive" }
            }
        ];
    
    writeDump(vectorstoreclient.addAll(articles));

    q = vectorstoreclient.search({
        "text": "vector database semantic search",
        "topK": 5,
        "minScore": 0.4,
        "filter": {
            "locale": "en-US",
            "publishedYear": { "$gte": 2025 },
            "section": { "$ne": "archive" }
        }
    });

    writeDump(q);
        } 
    catch (any e) {
        writeOutput("News search error:<br><br>");
        writeDump(e.detail);
    }

</cfscript>

Share this page

Was this page helpful?
We're glad. Tell us how this page helped.
We're sorry. Can you tell us what didn't work for you?
Thank you for your feedback. Your response will help improve this page.

On this page