https://github.com/oceanbase/seekdb-js
The JavaScript/TypeScript SDK for OceanBase or OceanBase seekdb.
https://github.com/oceanbase/seekdb-js
ai javascript sdk-js typescript
Last synced: about 1 month ago
JSON representation
The JavaScript/TypeScript SDK for OceanBase or OceanBase seekdb.
- Host: GitHub
- URL: https://github.com/oceanbase/seekdb-js
- Owner: oceanbase
- License: apache-2.0
- Created: 2026-01-12T02:35:48.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-26T08:05:58.000Z (about 2 months ago)
- Last Synced: 2026-03-26T13:36:40.682Z (about 2 months ago)
- Topics: ai, javascript, sdk-js, typescript
- Language: TypeScript
- Homepage: https://www.oceanbase.ai
- Size: 819 KB
- Stars: 19
- Watchers: 2
- Forks: 2
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
seekdb-js
[](https://www.npmjs.com/package/seekdb) [](https://www.npmjs.com/package/seekdb) [](https://www.typescriptlang.org/) [](https://nodejs.org/) [](https://github.com/oceanbase/seekdb-js/pulls)
Vector database SDK for JavaScript/TypeScript with built-in semantic search
Works seamlessly with seekdb and OceanBase
For complete usage, see the official documentation.
## Table of contents
[Why seekdb-js?](#why-seekdb-js)
[Packages](#packages)
[Installation](#installation)
[Running Modes](#running-modes)
[Quick Start](#quick-start)
[Usage Guide](#usage-guide)
[Examples](#examples)
[Development](#development)
[License](#license)
## Why seekdb-js?
- **Auto Vectorization** - Automatic embedding generation, no manual vector calculation needed
- **Semantic Search** - Vector-based similarity search for natural language queries
- **Hybrid Search** - Combine keyword matching with semantic search
- **Multiple Embedding Functions** - Built-in support for local and cloud embedding providers
- **TypeScript Native** - Full TypeScript support with complete type definitions
## Packages
This is a monorepo containing:
| Package | Description |
| ------------------------ | --------------------------------------------------------------------------- |
| `seekdb` | Core SDK for seekdb operations |
| `@seekdb/default-embed` | Local embedding function using Xenova/all-MiniLM-L6-v2 model (default) |
| `@seekdb/qwen` | DashScope/Tongyi Qianwen cloud embedding service |
| `@seekdb/openai` | OpenAI cloud embedding service |
| `@seekdb/jina` | Jina AI multimodal embedding service |
| `@seekdb/bm25` | BM25 sparse embedding function for efficient text-based keyword search |
| `@seekdb/prisma-adapter` | Prisma driver adapter for seekdb Embedded (use Prisma with seekdb Embedded) |
## Installation
```bash
npm install seekdb @seekdb/default-embed
```
- **Embedded mode**: No seekdb server deployment required; use locally after install.
- **Server mode**: Deploy seekdb or OceanBase first; see [official deployment docs](https://www.oceanbase.ai/docs/deploy-overview/).
## Running Modes
The SDK supports two modes; the constructor arguments to `SeekdbClient` determine which is used. For database management (create/list/get/delete database), use `SeekdbAdminClient()` which returns a `SeekdbClient` instance.
| Mode | Parameter | Description |
| ------------ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Embedded** | `path` (database directory path) | Runs locally with no separate seekdb server; data is stored under the given path (e.g. `./seekdb.db`). Requires native addon `@seekdb/js-bindings`. |
| **Server** | `host` (and `port`, `user`, `password`, etc.) | Connects to a remote seekdb or OceanBase instance. |
**OceanBase and seekdb**: OceanBase is compatible with seekdb and can be understood as its distributed, multi-tenant, etc. version. seekdb-js therefore supports **OceanBase server mode** with the same API: use the same `SeekdbClient` / `SeekdbAdminClient` and connection parameters; when connecting to OceanBase, additionally pass `tenant` (e.g. `"sys"` or your tenant name). See [OceanBase mode](#oceanbase-mode-server-mode-with-tenant) below.
- **SeekdbClient**: Pass `path` for embedded mode, or `host` (and port, user, password, etc.) for server mode.
- **SeekdbAdminClient()**: For admin operations only; pass `path` for embedded or `host` for server. In embedded mode you do not specify a database name.
## Quick Start
**Embedded mode** (local file, no server):
```typescript
import { SeekdbClient } from "seekdb";
// 1. Connect
const client = new SeekdbClient({
path: "./seekdb.db",
database: "test",
});
// 2. Create collection
const collection = await client.createCollection({ name: "my_collection" });
// 3. Add data (auto-vectorized using @seekdb/default-embed)
await collection.add({
ids: ["1", "2"],
documents: ["Hello world", "seekdb is fast"],
});
// 4. Search
const results = await collection.query({ queryTexts: "Hello", nResults: 5 });
console.log("query results", results);
```
**Server mode** (connect to a deployed seekdb):
```typescript
import { SeekdbClient } from "seekdb";
// 1. Connect
const client = new SeekdbClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
});
// 2. Create collection
const collection = await client.createCollection({ name: "my_collection" });
// 3. Add data (auto-vectorized using @seekdb/default-embed)
await collection.add({
ids: ["1", "2"],
documents: ["Hello world", "seekdb is fast"],
});
// 4. Search
const results = await collection.query({ queryTexts: "Hello", nResults: 5 });
console.log("query results", results);
```
## Usage Guide
This section covers basic usage. See the [official SDK documentation](https://www.oceanbase.ai/docs/seekdb-js-get-started) for full details.
### Client Connection
**Embedded mode** (local database file):
```typescript
import { SeekdbClient } from "seekdb";
const client = new SeekdbClient({
path: "./seekdb.db", // database file path
database: "test",
});
```
**Server mode**:
```typescript
import { SeekdbClient } from "seekdb";
const client = new SeekdbClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
});
```
**OceanBase mode** (server mode with tenant): OceanBase is compatible with seekdb (distributed, multi-tenant, etc.). Use the same server-mode connection; when the backend is OceanBase, pass `tenant` (e.g. `"sys"` or your tenant name):
```typescript
const client = new SeekdbClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
tenant: "sys", // or your OceanBase tenant
});
```
### Create Collection
You can create a collection without any configuration; the default embedding function will be used for vectorization. Ensure `@seekdb/default-embed` is installed first.
```typescript
const collection = await client.createCollection({
name: "my_collection",
});
```
#### Schema API
A schema defines which indexes are available on a collection:
- **FulltextIndexConfig** - For keyword-based full-text search
- **VectorIndexConfig** - For dense vector similarity search
- **SparseVectorIndexConfig** - For sparse vector similarity search
Examples for creating the three index types:
**FulltextIndexConfig**
```typescript
const schema = new Schema({
fulltextIndex: new FulltextIndexConfig("ik", { ik_mode: "smart" }),
});
const collection = await client.createCollection({
name: "ft_collection",
schema,
});
```
**VectorIndexConfig**
If you do not set `embeddingFunction`, the default embedding function is used. Ensure `@seekdb/default-embed` is installed.
```typescript
const schema = new Schema({
vectorIndex: new VectorIndexConfig({
hnsw: { dimension: 384, distance: "cosine" },
}),
});
const collection = await client.createCollection({
name: "vec_collection",
schema,
});
```
To use a custom embedding function, install one of the provided packages or implement your own. See the [official SDK documentation](https://www.oceanbase.ai/docs/seekdb-js-get-started) for details.
Take `@seekdb/qwen` as an example:
```bash
npm install @seekdb/qwen
```
```typescript
import { QwenEmbeddingFunction } from "@seekdb/qwen";
const qwenEF = new QwenEmbeddingFunction();
const schema = new Schema({
vectorIndex: new VectorIndexConfig({
hnsw: { dimension: 384, distance: "cosine" },
embeddingFunction: qwenEF,
}),
});
const collection = await client.createCollection({
name: "my_collection",
schema,
});
```
If you don't need an embedding function, set `embeddingFunction` to `null`.
```typescript
const schema = new Schema({
vectorIndex: new VectorIndexConfig({
hnsw: { dimension: 384, distance: "cosine" },
embeddingFunction: null,
}),
});
const collection = await client.createCollection({
name: "vec_collection",
schema,
});
```
**SparseVectorIndexConfig**
You can use the provided `@seekdb/bm25` as the sparse embedding function or implement your own.
```bash
npm install @seekdb/bm25
```
```typescript
import { Bm25EmbeddingFunction } from "@seekdb/bm25";
import { K } from "seekdb";
const schema = new Schema({
sparseVectorIndex: new SparseVectorIndexConfig({
sourceKey: K.DOCUMENT,
embeddingFunction: new Bm25EmbeddingFunction(),
}),
});
const collection = await client.createCollection({
name: "sparse_collection",
schema,
});
```
### Add Data
The embedding function defined in `Schema` is used automatically for vectorization. No need to set it again.
```typescript
await collection.add({
ids: ["1", "2"],
documents: ["Hello world", "seekdb is fast"],
metadatas: [{ category: "test" }, { category: "db" }],
});
```
You can also pass a vector or an array of vectors directly.
```typescript
const qwenEF = new QwenEmbeddingFunction();
await collection.add({
ids: ["1", "2"],
documents: ["Hello world", "seekdb is fast"],
metadatas: [{ category: "test" }, { category: "db" }],
embeddings: [
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
],
});
```
### Query Data
**Get Data**
The `get() `method is used to retrieve documents from a collection without performing vector similarity search.
```typescript
const results = await collection.get({
ids: ["1", "2"],
});
```
**Semantic Search**
The `query()` method is used to execute vector similarity search to find documents most similar to the query vector.
The embedding function defined in `Schema` is used automatically for vectorization. No need to set it again.
```typescript
const results = await collection.query({
queryTexts: "Hello",
nResults: 5,
});
```
You can also pass a vector or an array of vectors directly.
```typescript
const results = await collection.query({
queryEmbeddings: [
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
],
nResults: 5,
});
```
Specify `queryKey` to run sparse vector search. If a sparse embedding function is defined, `queryTexts` will be vectorized automatically.
```typescript
import
import { K } from "seekdb";
const results = await collection.query({
queryTexts: "artificial intelligence",
// Use sparse vector index, default by K.EMBEDDING
queryKey: K.EMBEDDING,
nResults: 3,
});
```
You can also supply your own sparse vectors for search.
```typescript
const queryVector: SparseVector = { 1234: 0.5, 5678: 0.8 };
const results = await collection.query({
queryEmbeddings: queryVector,
queryKey: K.SPARSE_EMBEDDING,
nResults: 5,
});
```
**Hybrid Search (Keyword + Semantic)**
The `hybridSearch()` combines full-text search and vector similarity search with ranking.
```typescript
const hybridResults = await collection.hybridSearch({
query: { whereDocument: { $contains: "seekdb" } },
knn: { queryTexts: ["fast database"] },
nResults: 5,
});
```
You can also pass a vector or an array of vectors directly.
```typescript
const hybridResults = await collection.hybridSearch({
query: { whereDocument: { $contains: "seekdb" } },
knn: {
queryEmbeddings: [
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
],
},
nResults: 5,
});
```
### Embedding Functions
The SDK supports multiple Embedding Functions for generating vectors locally or in the cloud.
For complete usage, see the official documentation.
#### Default Embedding
Uses a local model (`Xenova/all-MiniLM-L6-v2`) by default. No API Key required. Suitable for quick development and testing.
No configuration is needed to use the default model.
First install the built-in model:
```bash
npm install @seekdb/default-embed
```
Then use it as-is; it will auto-vectorize:
```typescript
const collection = await client.createCollection({
name: "local_embed_collection",
});
```
#### Qwen Embedding
Uses DashScope's cloud Embedding service (Qwen/Tongyi Qianwen). Suitable for production environments.
```bash
npm install @seekdb/qwen
```
```typescript
import { QwenEmbeddingFunction } from "@seekdb/qwen";
const qwenEmbed = new QwenEmbeddingFunction({
// Your DashScope environment variable name, defaults to 'DASHSCOPE_API_KEY'
apiKeyEnvVar: 'DASHSCOPE_API_KEY'
// Optional, defaults to 'text-embedding-v4'
modelName: "text-embedding-v4",
});
const collection = await client.createCollection({
name: "qwen_embed_collection",
embeddingFunction: qwenEmbed,
});
```
#### OpenAI Embedding
Uses OpenAI's embedding API. Suitable for production environments with OpenAI integration.
```bash
npm install @seekdb/openai
```
```typescript
import { OpenAIEmbeddingFunction } from "@seekdb/openai";
const openaiEmbed = new OpenAIEmbeddingFunction({
// Your openai environment variable name, defaults to 'OPENAI_API_KEY'
apiKeyEnvVar: 'OPENAI_API_KEY'
// Optional, defaults to 'text-embedding-3-small'
modelName: "text-embedding-3-small",
});
const collection = await client.createCollection({
name: "openai_embed_collection",
embeddingFunction: openaiEmbed,
});
```
#### Jina Embedding
Uses Jina AI's embedding API. Supports multimodal embeddings.
```bash
npm install @seekdb/jina
```
```typescript
import { JinaEmbeddingFunction } from "@seekdb/jina";
const jinaEmbed = new JinaEmbeddingFunction({
// Your jina environment variable name, defaults to 'JINA_API_KEY'
apiKeyEnvVar: 'JINA_API_KEY'
// Optional, defaults to jina-clip-v2
modelName: "jina-clip-v2",
});
const collection = await client.createCollection({
name: "jina_embed_collection",
embeddingFunction: jinaEmbed,
});
```
#### Custom Embedding Function
You can also use your own custom embedding function.
First, implement the `EmbeddingFunction` interface:
```typescript
import type { EmbeddingFunction } from "seekdb";
import { registerEmbeddingFunction } from "seekdb";
interface MyCustomEmbeddingConfig {
apiKeyEnv: string;
}
class MyCustomEmbeddingFunction implements EmbeddingFunction {
// The name of the `embeddingFunction`, must be unique.
readonly name = "my_custom_embedding";
private apiKeyEnv: string;
dimension: number;
constructor(config: MyCustomEmbeddingConfig) {
this.apiKeyEnv = config.apiKeyEnv;
this.dimension = 384;
}
// Implement your vector generation code here
async generate(texts: string[]): Promise {
const embeddings: number[][] = [];
return embeddings;
}
// The configuration of the current `embeddingFunction` instance, used to restore this instance
getConfig(): MyCustomEmbeddingConfig {
return {
apiKeyEnv: this.apiKeyEnv,
};
}
// Create a new instance of the current `embeddingFunction` based on the provided configuration
static buildFromConfig(config: MyCustomEmbeddingConfig): EmbeddingFunction {
return new MyCustomEmbeddingFunction(config);
}
}
// Register the constructor
registerEmbeddingFunction("my_custom_embedding", MyCustomEmbeddingFunction);
```
Then use it:
```typescript
const customEmbed = new MyCustomEmbeddingFunction({
apiKeyEnv: "MY_CUSTOM_API_KEY_ENV",
});
const collection = await client.createCollection({
name: "custom_embed_collection",
configuration: {
dimension: 384,
distance: "cosine",
},
embeddingFunction: customEmbed,
});
```
### BM25 Sparse Embedding
BM25 (Best Matching 25) is a sparse embedding function that uses term frequency and document length normalization for efficient text search. It's particularly useful for keyword-based search scenarios.
```bash
npm install @seekdb/bm25
```
```typescript
import { SeekdbClient, Schema, SparseVectorIndexConfig, K } from "seekdb";
import { Bm25EmbeddingFunction } from "@seekdb/bm25";
const bm25 = new Bm25EmbeddingFunction({
k: 1.2, // Term frequency saturation
b: 0.75, // Document length normalization
avgDocLength: 256, // Average document length
tokenMaxLength: 40, // Maximum token length
stopwords: ["a", "an", "the"], // Custom stopwords
});
const collection = await client.createCollection({
name: "bm25_collection",
schema: new Schema({
sparseVectorIndex: new SparseVectorIndexConfig({
sourceKey: K.DOCUMENT,
embeddingFunction: bm25,
}),
}),
});
```
For more details, see [BM25 Embedding Guide](./docs/bm25-embedding-guide.md).
#### Custom Sparse Embedding Function
Implement your own sparse embedding function:
```typescript
import {
SparseEmbeddingFunction,
SparseVector,
registerSparseEmbeddingFunction,
EmbeddingConfig,
} from "seekdb";
interface MySparseConfig {
vocabSize: number;
}
class MySparseEmbeddingFunction implements SparseEmbeddingFunction {
readonly name = "my_sparse";
private vocabSize: number;
constructor(config: MySparseConfig) {
this.vocabSize = config.vocabSize;
}
// Implement your vector generation code here
async generate(texts: string[]): Promise {
const embeddings: number[][] = [];
return embeddings;
}
// Generate sparse vectors for queries (can be different)
async generateForQueries(texts: string[]): Promise {
return this.generate(texts);
}
// Return configuration for persistence
getConfig(): EmbeddingConfig {
return { vocabSize: this.vocabSize };
}
// Static factory method
static buildFromConfig(config: EmbeddingConfig): SparseEmbeddingFunction {
return new MySparseEmbeddingFunction(config as MySparseConfig);
}
}
// Register the function
registerSparseEmbeddingFunction("my_sparse", MySparseEmbeddingFunction);
// Use it
const collection = await client.createCollection({
name: "my_sparse_collection",
schema: {
sparseVectorIndex: new SparseVectorIndexConfig({
sourceKey: K.DOCUMENT,
embeddingFunction: new MySparseEmbeddingFunction({ vocabSize: 100000 }),
}),
},
});
```
### Vector search + relational tables
You can combine vector (or hybrid) search with relational tables: run `collection.query()` or `collection.hybridSearch()` to get `ids`, then query your relational table by those ids. For type-safe relational queries, prefer an ORM (see [Integration with ORM](#integration-with-orm)); here is a raw-SQL recipe.
**Recipe**
1. Get ids (and optional metadata) from vector/hybrid search.
2. Query the relational table with `client.execute()`. For `WHERE id IN (...)` with MySQL/mysql2, use parameterized placeholders to avoid SQL injection: one `?` per id and pass the ids array as params.
**Example (TypeScript)** — hybrid search, then fetch users by id and merge:
```typescript
const client = new SeekdbClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
});
const collection = await client.getCollection({ name: "my_collection" });
// 1. Hybrid search → get ids
const hybridResult = await collection.hybridSearch({
query: { whereDocument: { $contains: "seekdb" } },
knn: { queryTexts: ["fast database"] },
nResults: 5,
});
const ids = hybridResult.ids?.flat().filter(Boolean) ?? []; // e.g. string[]
// 2. Query relational table by ids (parameterized)
type UserRow = { id: string; name: string };
let users: UserRow[] = [];
if (ids.length > 0) {
const placeholders = ids.map(() => "?").join(",");
const rows = await client.execute(
`SELECT id, name FROM users WHERE id IN (${placeholders})`,
ids
);
users = (rows ?? []) as UserRow[];
}
// 3. Merge: e.g. map ids to (vector result + user row)
const merged = ids.map((id) => ({
id,
user: users.find((u) => u.id === id) ?? null,
}));
```
**Transactions**: There is no explicit transaction API on the client. For transactions that span both vector and relational operations, use a separate mysql2 connection (same DB config) and run `beginTransaction()` / `commit()` / `rollback()` on that connection (see [Integration with ORM](#integration-with-orm)).
### Integration with ORM
Use seekdb-js for vector/full-text/hybrid search and an ORM (Drizzle or Prisma) for type-safe relational tables. seekdb is MySQL-compatible in both modes. **Server mode**: same database, two connections (SeekdbClient + ORM). **Embedded mode**: Drizzle uses `drizzle-orm/mysql-proxy` with a callback around `client.execute()`; Prisma uses [@seekdb/prisma-adapter](https://www.npmjs.com/package/@seekdb/prisma-adapter).
#### Drizzle
**Server mode**: Create a mysql2 connection with the same DB config as SeekdbClient and pass it to `drizzle(conn)`.
```typescript
import { createConnection } from "mysql2/promise";
import { SeekdbClient } from "seekdb";
import { drizzle } from "drizzle-orm/mysql2";
import { inArray } from "drizzle-orm";
import { users } from "./schema"; // mysqlTable, relational only; vector tables via Collection
const dbConfig = {
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
};
const client = new SeekdbClient(dbConfig);
const conn = await createConnection(dbConfig);
const db = drizzle(conn);
const collection = await client.getCollection({ name: "docs" });
const result = await collection.hybridSearch({
query: { whereDocument: { $contains: "seekdb" } },
knn: { queryTexts: ["database"] },
nResults: 5,
});
const ids = result.ids?.flat().filter(Boolean) ?? [];
const usersList = await db.select().from(users).where(inArray(users.id, ids));
// when done: await conn.end(); await client.close();
```
**Embedded mode**: Use `drizzle-orm/mysql-proxy` with a callback that runs SQL via `client.execute()` and returns `{ rows }`. See [seekdb-drizzle](./examples/seekdb-drizzle/index-embedded.ts) for a runnable sample.
#### Prisma
**Server mode**: Use SeekdbClient and PrismaClient with `DATABASE_URL` pointing to the same database.
```typescript
import { SeekdbClient } from "seekdb";
import { PrismaClient } from "@prisma/client";
const client = new SeekdbClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
database: "test",
});
const prisma = new PrismaClient(); // DATABASE_URL="mysql://root:@127.0.0.1:2881/test"
const collection = await client.getCollection({ name: "docs" });
const result = await collection.hybridSearch({
query: { whereDocument: { $contains: "seekdb" } },
knn: { queryTexts: ["database"] },
nResults: 5,
});
const ids = result.ids?.flat().filter(Boolean) ?? [];
const users = await prisma.user.findMany({ where: { id: { in: ids } } });
// merge as needed; when done: await client.close(); await prisma.$disconnect();
```
Set `DATABASE_URL` to the same host/port/user/password/database (e.g. `mysql://user:password@host:port/database`). OceanBase: see Prisma/MySQL tenant docs.
**Embedded mode**: Use [@seekdb/prisma-adapter](https://www.npmjs.com/package/@seekdb/prisma-adapter) with `PrismaClient({ adapter })` so Prisma runs SQL via `client.execute()`. See [seekdb-prisma](./examples/seekdb-prisma/index-embedded.ts); run `pnpm run start:embedded` in that example.
### Database Management
Use `SeekdbAdminClient` for database management. It supports both embedded and server modes.
**Embedded mode** (local database file):
```typescript
import { SeekdbAdminClient } from "seekdb";
const admin = new SeekdbAdminClient({ path: "./seekdb.db" });
await admin.createDatabase("new_database");
const databases = await admin.listDatabases();
const db = await admin.getDatabase("new_database");
await admin.deleteDatabase("new_database");
await admin.close();
```
**Server mode**:
```typescript
import { SeekdbAdminClient } from "seekdb";
const admin = new SeekdbAdminClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
});
await admin.createDatabase("new_database");
const databases = await admin.listDatabases();
const db = await admin.getDatabase("new_database");
await admin.deleteDatabase("new_database");
await admin.close();
```
**OceanBase mode** (server mode with tenant): add `tenant` (e.g. `"sys"` or your tenant name) to the config:
```typescript
const admin = new SeekdbAdminClient({
host: "127.0.0.1",
port: 2881,
user: "root",
password: "",
tenant: "sys", // or your OceanBase tenant
});
await admin.createDatabase("new_database");
const databases = await admin.listDatabases();
const db = await admin.getDatabase("new_database");
await admin.deleteDatabase("new_database");
await admin.close();
```
`AdminClient()` is available as a factory and returns a `SeekdbClient` configured for admin operations.
## Examples
Check out the [examples](./examples) directory for complete usage examples:
**Basic examples** (root `examples/`):
- [simple-example.ts](./examples/simple-example.ts) - Basic usage
- [complete-example.ts](./examples/complete-example.ts) - All features
- [hybrid-search-example.ts](./examples/hybrid-search-example.ts) - Hybrid search
**ORM integration** (vector + relational tables):
- [seekdb-drizzle](./examples/seekdb-drizzle) - Drizzle ORM (Server: same DB two connections; Embedded: mysql-proxy)
- [seekdb-prisma](./examples/seekdb-prisma) - Prisma ORM (Server: DATABASE_URL; Embedded: [@seekdb/prisma-adapter](https://www.npmjs.com/package/@seekdb/prisma-adapter))
To run the examples, see [Run Examples](./DEVELOP.md#run-examples) in the development guide.
## Development
See [DEVELOP.md](./DEVELOP.md) for details on development, testing, and contributing.
## License
This package is licensed under [Apache 2.0](./LICENSE).