Skip to content

Latest commit

 

History

History
131 lines (105 loc) · 4.77 KB

File metadata and controls

131 lines (105 loc) · 4.77 KB
name mobile-vector-search-ios
summary On-device vector search with Couchbase Lite for iOS/macOS (Swift) — VectorIndexConfiguration, creating vector indexes, embedding vectors in documents, running vector similarity queries, lazy vector indexes, hybrid FTS + vector search, distance metrics (cosine, euclidean, dot product), encoding (SQ, PQ)
description On-device vector search with Couchbase Lite for iOS/macOS (Swift) — VectorIndexConfiguration, creating vector indexes, embedding vectors in documents, running vector similarity queries, lazy vector indexes, hybrid FTS + vector search, distance metrics (cosine, euclidean, dot product), encoding (SQ, PQ)
compatibility Couchbase Lite iOS/macOS 4.x Enterprise Edition (Swift). Requires the Vector Search extension.
metadata
last_verified handoff
2026-05
condition skill
user is on Android or Kotlin
mobile-vector-search-android
condition skill
user asks about server-side vector search or RAG
search-concepts
condition skill
user asks about iOS CRUD or queries
mobile-ios

Platform-agnostic concepts: shared/mobile/vector-search-concepts.md

On-Device Vector Search — Couchbase Lite iOS/macOS

Vector search runs entirely on-device — no network required. Requires Enterprise Edition and the Vector Search extension.

Setup

Add to your Package.swift or Podfile:

// Swift Package Manager
.package(url: "https://github.com/couchbase/couchbase-lite-ios-ee", from: "4.x.x")
// target dependency: "CouchbaseLiteSwift-EE-VectorSearch"

Enable before opening any database:

import CouchbaseLiteSwift
VectorSearch.enable()

Create a vector index

var vectorConfig = VectorIndexConfiguration(expression: "embedding", dimensions: 384, centroids: 100)
vectorConfig.metric   = .cosine
vectorConfig.encoding = .none  // or .sq(bits: 8), .pq(subquantizers: 8, bits: 8)
try collection.createIndex(withName: "vector_index", config: vectorConfig)
  • dimensions: 384 — must match your embedding model's output size
  • centroids: 100 — higher = more accurate, slower to build
  • .cosine — use .euclidean or .dotProduct depending on your model

Store a document with an embedding

let embedding: [Float] = myEmbeddingModel.encode("comfortable running shoes")

var doc = MutableDocument(id: "product::1")
doc.setString("Trail Runner Pro", forKey: "name")
doc.setString("footwear", forKey: "category")
doc.setArray(MutableArrayObject(data: embedding.map { $0 as NSNumber }), forKey: "embedding")
try collection.save(document: doc)

Run a vector similarity query

let queryVector: [Float] = myEmbeddingModel.encode("comfortable running shoes")

let query = try database.createQuery("""
    SELECT name, category, APPROX_VECTOR_DISTANCE(embedding, $vector) AS distance
    FROM _
    ORDER BY APPROX_VECTOR_DISTANCE(embedding, $vector)
    LIMIT 5
""")
let params = Parameters()
params.setArray(MutableArrayObject(data: queryVector.map { $0 as NSNumber }), forKey: "vector")
query.parameters = params

let results = try query.execute().allResults()
for result in results {
    print("\(result.string(forKey: "name")!) distance=\(result.double(forKey: "distance"))")
}

Lazy vector index

Use a lazy index when embeddings are generated asynchronously:

var lazyConfig = VectorIndexConfiguration(expression: "embedding", dimensions: 384, centroids: 100)
lazyConfig.isLazy = true
try collection.createIndex(withName: "lazy_vector_index", config: lazyConfig)

// Updater loop — run in a background Task
func updateVectorIndex() async throws {
    while true {
        guard let updater = try collection.indexUpdater(forName: "lazy_vector_index", limit: 50) else { break }
        for i in 0..<updater.count {
            guard let text = updater.string(at: i, path: "text") else { continue }
            let embedding = myEmbeddingModel.encode(text)
            try updater.setVector(embedding, at: i)
        }
        try updater.finish()
    }
}

Hybrid FTS + vector search

let query = try database.createQuery("""
    SELECT name, APPROX_VECTOR_DISTANCE(embedding, $vector) AS distance
    FROM _
    WHERE MATCH(fts_index, $keyword)
    ORDER BY APPROX_VECTOR_DISTANCE(embedding, $vector)
    LIMIT 5
""")
let params = Parameters()
params.setArray(MutableArrayObject(data: queryVector.map { $0 as NSNumber }), forKey: "vector")
params.setString("running shoes", forKey: "keyword")
query.parameters = params

Distance metrics

Metric Use when
.cosine Normalized embeddings (most text/image models)
.euclidean Raw float vectors, spatial data
.dotProduct Unnormalized embeddings where magnitude matters