| 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 |
|
Platform-agnostic concepts: shared/mobile/vector-search-concepts.md
Vector search runs entirely on-device — no network required. Requires Enterprise Edition and the Vector Search extension.
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()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 sizecentroids: 100— higher = more accurate, slower to build.cosine— use.euclideanor.dotProductdepending on your model
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)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"))")
}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()
}
}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| Metric | Use when |
|---|---|
.cosine |
Normalized embeddings (most text/image models) |
.euclidean |
Raw float vectors, spatial data |
.dotProduct |
Unnormalized embeddings where magnitude matters |