{"id":20439399,"url":"https://github.com/skitsanos/lua-arangodb","last_synced_at":"2026-04-18T17:36:42.915Z","repository":{"id":153096215,"uuid":"589429070","full_name":"skitsanos/lua-arangodb","owner":"skitsanos","description":"ArangoDB Client for OpenResty","archived":false,"fork":false,"pushed_at":"2025-12-05T19:12:40.000Z","size":85,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-09T07:07:48.860Z","etag":null,"topics":["arangodb","arangodb-client","arangodb-driver","database","lua","lua-script","luajit","nginx","nginx-lua","nginx-luajit","rest"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skitsanos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-16T04:48:04.000Z","updated_at":"2025-12-07T12:50:32.000Z","dependencies_parsed_at":"2025-01-15T19:22:43.825Z","dependency_job_id":"01906e5b-23ba-4adc-8573-281ca5c53a20","html_url":"https://github.com/skitsanos/lua-arangodb","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/skitsanos/lua-arangodb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skitsanos%2Flua-arangodb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skitsanos%2Flua-arangodb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skitsanos%2Flua-arangodb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skitsanos%2Flua-arangodb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skitsanos","download_url":"https://codeload.github.com/skitsanos/lua-arangodb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skitsanos%2Flua-arangodb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31978538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T17:30:12.329Z","status":"ssl_error","status_checked_at":"2026-04-18T17:29:59.069Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arangodb","arangodb-client","arangodb-driver","database","lua","lua-script","luajit","nginx","nginx-lua","nginx-luajit","rest"],"created_at":"2024-11-15T09:17:09.994Z","updated_at":"2026-04-18T17:36:42.908Z","avatar_url":"https://github.com/skitsanos.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ArangoDB Client for OpenResty/Lua\n\nA comprehensive, modular ArangoDB client library for OpenResty/Lua with full HTTP API support.\n\n## Features\n\n- Full ArangoDB HTTP API coverage\n- Modular architecture with separate modules for each API area\n- Connection pooling and keepalive support\n- Both Basic and JWT authentication\n- AQL query execution with cursor pagination\n- Stream transactions support\n- Graph operations (Gharial API)\n- ArangoSearch views and analyzers\n- Vector indexes for semantic similarity search (v3.12.4+)\n- OpenAI-compatible embeddings generation (OpenAI, Ollama, vLLM, etc.)\n- Foxx microservices management\n- User and permission management\n- Cluster operations support\n\n## Installation\n\n### Dependencies\n\n```shell\nluarocks install lua-cjson\nluarocks install lbase64\nluarocks install lua-resty-http\n```\n\n### Manual Installation\n\nCopy the `src/arangodb` folder to your Lua package path.\n\n## Quick Start\n\n```lua\nlocal arangodb = require(\"arangodb\")\n\n-- Create client\nlocal client = arangodb.new({\n    endpoint = \"http://127.0.0.1:8529\",\n    username = \"root\",\n    password = \"password\",\n    database = \"_system\"\n})\n\n-- Get server version\nlocal version = client:version()\nprint(\"ArangoDB \" .. version.version)\n\n-- Execute AQL query\nlocal results = client.query:execute(\n    \"FOR doc IN users FILTER doc.age \u003e= @minAge RETURN doc\",\n    { minAge = 21 }\n)\n\n-- Create a document\nlocal doc = client.document:create(\"users\", {\n    name = \"Alice\",\n    age = 30\n})\n```\n\n## Configuration\n\n```lua\nlocal client = arangodb.new({\n    -- Required\n    endpoint = \"http://127.0.0.1:8529\",  -- ArangoDB server URL\n\n    -- Authentication (one of these is required)\n    username = \"root\",                    -- Basic auth username\n    password = \"password\",                -- Basic auth password\n    -- OR\n    token = \"jwt-token\",                  -- JWT bearer token\n\n    -- Optional\n    database = \"_system\",                 -- Default database (default: \"_system\")\n    timeout = 30000,                      -- Request timeout in ms (default: 30000)\n    keepalive = 60000,                    -- Keepalive timeout in ms (default: 60000)\n    pool_size = 100,                      -- Connection pool size (default: 100)\n    ssl_verify = false                    -- Verify SSL certificates (default: false)\n})\n```\n\n## API Reference\n\n### Client Methods\n\n```lua\n-- Get server version\nclient:version(details)              -- details: include detailed info\n\n-- Get storage engine info\nclient:engine()\n\n-- Check server availability\nclient:isAvailable()\n\n-- Switch database\nclient:useDatabase(name)\nclient:getDatabase()\n\n-- Raw HTTP methods\nclient:get(path, options)\nclient:post(path, body, options)\nclient:put(path, body, options)\nclient:patch(path, body, options)\nclient:delete(path, options)\n```\n\n### Database Operations (`client.db`)\n\n```lua\n-- List databases\nclient.db:list()                     -- All databases\nclient.db:listUser()                 -- User-accessible databases\nclient.db:current()                  -- Current database info\nclient.db:exists(name)               -- Check if database exists\n\n-- Create database\nclient.db:create(name, options, users)\n\n-- Drop database\nclient.db:drop(name)\n\n-- Shorthand query (uses client.query:execute)\nclient.db:query(aql, bindVars, options)\n```\n\n### Collection Operations (`client.collection`)\n\n```lua\n-- List collections\nclient.collection:list(excludeSystem)\n\n-- Get collection info\nclient.collection:get(name)\nclient.collection:properties(name)\nclient.collection:exists(name)\nclient.collection:count(name)\nclient.collection:figures(name)\nclient.collection:revision(name)\n\n-- Create collections\nclient.collection:create(name, options)\nclient.collection:createDocument(name, options)  -- type = 2\nclient.collection:createEdge(name, options)      -- type = 3\n\n-- Modify collections\nclient.collection:rename(name, newName)\nclient.collection:setProperties(name, properties)\nclient.collection:truncate(name)\nclient.collection:drop(name, isSystem)\n\n-- Memory management\nclient.collection:load(name)\nclient.collection:unload(name)\nclient.collection:loadIndexes(name)\nclient.collection:compact(name)\n```\n\n### Document Operations (`client.document`)\n\n```lua\n-- Read documents\nclient.document:get(collection, key, options)\nclient.document:exists(collection, key)\nclient.document:head(collection, key)\nclient.document:getMany(collection, keys, options)\n\n-- Create documents\nclient.document:create(collection, document, options)\nclient.document:createMany(collection, documents, options)\n\n-- Update documents\nclient.document:update(collection, key, document, options)\nclient.document:updateMany(collection, documents, options)\n\n-- Replace documents\nclient.document:replace(collection, key, document, options)\nclient.document:replaceMany(collection, documents, options)\n\n-- Delete documents\nclient.document:delete(collection, key, options)\nclient.document:deleteMany(collection, keys, options)\n\n-- Import/Export\nclient.document:import(collection, documents, options)\nclient.document:export(collection, options)\n```\n\n#### Document Options\n\n```lua\n{\n    waitForSync = true,      -- Wait for sync to disk\n    returnNew = true,        -- Return new document\n    returnOld = true,        -- Return old document\n    silent = false,          -- Don't return metadata\n    overwrite = false,       -- Overwrite existing\n    overwriteMode = \"update\", -- \"ignore\", \"update\", \"replace\", \"conflict\"\n    keepNull = true,         -- Keep null values in updates\n    mergeObjects = true,     -- Merge nested objects\n    ifMatch = \"rev\",         -- Conditional by revision\n}\n```\n\n### Query Operations (`client.query`)\n\n```lua\n-- Execute queries\nlocal results, cursor = client.query:execute(aql, bindVars, options)\nlocal all_results = client.query:all(aql, bindVars, options)  -- Auto-pagination\n\n-- Cursor operations\nclient.query:next(cursorId)\nclient.query:deleteCursor(cursorId)\n\n-- Iterator for large result sets\nfor doc in client.query:iterate(aql, bindVars, options) do\n    print(doc.name)\nend\n\n-- Query analysis\nclient.query:parse(aql, options)\nclient.query:explain(aql, bindVars, options)\n\n-- Running queries\nclient.query:listRunning(all)\nclient.query:kill(queryId)\n\n-- Slow query log\nclient.query:listSlow(all)\nclient.query:clearSlow(all)\n\n-- Query tracking\nclient.query:getTracking()\nclient.query:setTracking(properties)\n\n-- Query cache\nclient.query:getCacheProperties()\nclient.query:setCacheProperties(properties)\nclient.query:getCacheEntries()\nclient.query:clearCache()\n\n-- AQL functions\nclient.query:functions(namespace)\nclient.query:createFunction(name, code, isDeterministic)\nclient.query:deleteFunction(name, group)\n\n-- Optimizer rules\nclient.query:rules()\n```\n\n#### Query Options\n\n```lua\n{\n    count = true,            -- Return total count\n    batchSize = 1000,        -- Batch size for cursor\n    ttl = 30,                -- Cursor TTL in seconds\n    cache = true,            -- Use query cache\n    memoryLimit = 0,         -- Memory limit in bytes\n    fullCount = true,        -- Return full count (with LIMIT)\n    stream = true,           -- Stream results\n    profile = 2,             -- Profile level (0, 1, 2)\n    maxRuntime = 60,         -- Max runtime in seconds\n}\n```\n\n### Index Operations (`client.index`)\n\n```lua\n-- List indexes\nclient.index:list(collection, withStats, withHidden)\nclient.index:get(indexId)\nclient.index:getByName(collection, indexName)\nclient.index:exists(indexId)\n\n-- Create indexes\nclient.index:create(collection, definition)\nclient.index:createPersistent(collection, fields, options)\nclient.index:createGeo(collection, fields, options)\nclient.index:createFulltext(collection, fields, options)  -- Deprecated\nclient.index:createTTL(collection, fields, expireAfter, options)\nclient.index:createZKD(collection, fields, options)\nclient.index:createMDI(collection, fields, options)\nclient.index:createInverted(collection, fields, options)\n\n-- Vector index for semantic similarity search (v3.12.4+)\n-- NOTE: Requires --vector-index startup option and documents must exist first\nclient.index:createVector(collection, field, params, options)\n\n-- Drop index\nclient.index:drop(indexId)\n\n-- Ensure index exists\nlocal idx, created = client.index:ensure(collection, definition)\n```\n\n#### Vector Search (v3.12.4+)\n\nArangoDB supports vector similarity search for semantic/AI applications. Vector indexes use the Faiss library for approximate nearest neighbor (ANN) search.\n\n**Requirements:**\n- Server must be started with `--experimental-vector-index=true`\n- Documents with vector embeddings must exist **before** creating the index\n- Once enabled, vector-index cannot be disabled (permanent RocksDB change)\n\n**Creating a Vector Index:**\n\n```lua\n-- Documents must have embeddings first\nfor i = 1, 1000 do\n    client.document:create(\"documents\", {\n        text = \"Document \" .. i,\n        embedding = generate_embedding(...)  -- 384-dim vector\n    })\nend\n\n-- Then create the vector index\nlocal idx = client.index:createVector(\"documents\", \"embedding\", {\n    metric = \"cosine\",           -- \"cosine\", \"l2\", or \"innerProduct\"\n    dimension = 384,             -- vector array length\n    nLists = 66,                 -- ~N/15 where N is document count\n    defaultNProbe = 10,          -- neighboring centroids to search (higher = slower but better)\n    trainingIterations = 25      -- optional, default: 25\n})\n```\n\n**Vector Search Functions:**\n\n| Function | Metric | Sort Order | Value Range | Version |\n|----------|--------|------------|-------------|---------|\n| `APPROX_NEAR_COSINE()` | cosine | DESC | [-1, 1] | v3.12.4+ |\n| `APPROX_NEAR_L2()` | l2 | ASC | [0, ∞) | v3.12.4+ |\n| `APPROX_NEAR_INNER_PRODUCT()` | innerProduct | DESC | (-∞, ∞) | v3.12.6+ |\n| `COSINE_SIMILARITY()` | - | DESC | [-1, 1] | v3.9.0+ (exact, no index) |\n\n**Query Examples:**\n\n```lua\n-- Approximate search using vector index (fast, for large datasets)\nlocal results = client.query:execute([[\n    FOR doc IN documents\n      SORT APPROX_NEAR_COSINE(doc.embedding, @query) DESC\n      LIMIT 10\n      RETURN doc\n]], { query = query_vector })\n\n-- With similarity score and custom nProbe\nlocal results = client.query:execute([[\n    FOR doc IN documents\n      LET similarity = APPROX_NEAR_COSINE(doc.embedding, @query, { nProbe: 20 })\n      SORT similarity DESC\n      LIMIT 10\n      RETURN MERGE({ similarity }, doc)\n]], { query = query_vector })\n\n-- Pre-filtering (v3.12.6+)\nlocal results = client.query:execute([[\n    FOR doc IN documents\n      FILTER doc.category == @category\n      SORT APPROX_NEAR_COSINE(doc.embedding, @query) DESC\n      LIMIT 10\n      RETURN doc\n]], { query = query_vector, category = \"tech\" })\n\n-- Exact cosine similarity (no index needed, for small datasets)\nlocal results = client.query:execute([[\n    FOR doc IN documents\n      LET sim = COSINE_SIMILARITY(doc.embedding, @query)\n      FILTER sim \u003e 0.8\n      SORT sim DESC\n      LIMIT 10\n      RETURN { doc, similarity: sim }\n]], { query = query_vector })\n\n-- Batch similarity with 2D array\nlocal results = client.query:execute([[\n    RETURN COSINE_SIMILARITY(@vectors, @query)\n]], {\n    vectors = {{0,1,0,1}, {1,0,0,1}, {1,1,1,0}},\n    query = {1,1,1,1}\n})\n-- Returns: [0.707, 0.707, 0.866]\n```\n\n**Metric Selection:**\n\n| Metric | Use Case | Notes |\n|--------|----------|-------|\n| `cosine` | Text embeddings, normalized vectors | Auto-normalizes vectors |\n| `l2` | Image features, spatial data | Euclidean distance |\n| `innerProduct` | When magnitude matters | Faster than cosine (no normalization) |\n\n### Graph Operations (`client.graph`)\n\n```lua\n-- Graph management\nclient.graph:list()\nclient.graph:get(name)\nclient.graph:exists(name)\nclient.graph:create(name, edgeDefinitions, options)\nclient.graph:drop(name, dropCollections)\n\n-- Vertex collections\nclient.graph:listVertexCollections(graphName)\nclient.graph:addVertexCollection(graphName, collection, options)\nclient.graph:removeVertexCollection(graphName, collection, dropCollection)\n\n-- Edge definitions\nclient.graph:listEdgeDefinitions(graphName)\nclient.graph:addEdgeDefinition(graphName, definition, options)\nclient.graph:replaceEdgeDefinition(graphName, edgeCollection, definition, options)\nclient.graph:removeEdgeDefinition(graphName, edgeCollection, options)\n\n-- Vertex CRUD\nclient.graph:getVertex(graphName, collection, key, options)\nclient.graph:createVertex(graphName, collection, vertex, options)\nclient.graph:updateVertex(graphName, collection, key, vertex, options)\nclient.graph:replaceVertex(graphName, collection, key, vertex, options)\nclient.graph:deleteVertex(graphName, collection, key, options)\n\n-- Edge CRUD\nclient.graph:getEdge(graphName, collection, key, options)\nclient.graph:createEdge(graphName, collection, edge, options)\nclient.graph:updateEdge(graphName, collection, key, edge, options)\nclient.graph:replaceEdge(graphName, collection, key, edge, options)\nclient.graph:deleteEdge(graphName, collection, key, options)\n\n-- Traversal\nclient.graph:traverse(startVertex, options)\n```\n\n### Transaction Operations (`client.transaction`)\n\n```lua\n-- JavaScript transaction (single request)\nlocal result = client.transaction:execute({\n    collections = { read = {\"col1\"}, write = {\"col2\"} },\n    params = { userId = \"123\", amount = 50 },\n    action = [[\n        function(params) {\n            var db = require('@arangodb').db;\n            var user = db.col1.document(params.userId);\n            db.col2.insert({ debit: params.amount, user: user._key });\n            return \"success\";\n        }\n    ]]\n})\n\n-- Stream transactions (multi-request)\nlocal tx = client.transaction:begin(collections, options)\nlocal status = client.transaction:status(tx.id)\nclient.transaction:commit(tx.id)\nclient.transaction:abort(tx.id)\nclient.transaction:list()\n\n-- Transaction helper (auto commit/abort)\nclient.transaction:run(collections, function(txId)\n    -- Operations here\n    return result\nend, options)\n\n-- Transaction-aware operations\nclient.transaction:query(txId, aql, bindVars, options)\nclient.transaction:createDocument(txId, collection, document, options)\nclient.transaction:updateDocument(txId, collection, key, document, options)\nclient.transaction:deleteDocument(txId, collection, key, options)\n```\n\n### User Operations (`client.user`)\n\n```lua\n-- User management\nclient.user:list()\nclient.user:get(username)\nclient.user:exists(username)\nclient.user:create(username, password, options)\nclient.user:update(username, options)\nclient.user:replace(username, password, options)\nclient.user:delete(username)\n\n-- Database permissions\nclient.user:getDatabasePermission(username, database)\nclient.user:setDatabasePermission(username, database, permission)\nclient.user:clearDatabasePermission(username, database)\nclient.user:listDatabasePermissions(username, full)\n\n-- Collection permissions\nclient.user:getCollectionPermission(username, database, collection)\nclient.user:setCollectionPermission(username, database, collection, permission)\nclient.user:clearCollectionPermission(username, database, collection)\n\n-- Convenience methods\nclient.user:grantDatabase(username, database)           -- rw\nclient.user:grantDatabaseReadOnly(username, database)   -- ro\nclient.user:revokeDatabase(username, database)          -- none\nclient.user:grantCollection(username, database, collection)\nclient.user:grantCollectionReadOnly(username, database, collection)\nclient.user:revokeCollection(username, database, collection)\n```\n\n### Admin Operations (`client.admin`)\n\n```lua\n-- Server info\nclient.admin:version(details)\nclient.admin:engine()\nclient.admin:serverId()\nclient.admin:serverRole()\nclient.admin:serverAvailability()\nclient.admin:serverMode()\nclient.admin:setServerMode(mode)\n\n-- Statistics\nclient.admin:statistics()\nclient.admin:statisticsDescription()\nclient.admin:metrics(serverId)\n\n-- Logs\nclient.admin:logs(options)\nclient.admin:logLevel(serverId)\nclient.admin:setLogLevel(levels, serverId)\n\n-- Cluster operations\nclient.admin:clusterHealth()\nclient.admin:clusterEndpoints()\nclient.admin:clusterStatistics(dbserver)\nclient.admin:maintenance(serverId, mode, options)\nclient.admin:cleanOutServer(serverId)\nclient.admin:moveShard(options)\nclient.admin:rebalanceShards(options)\n\n-- Async jobs\nclient.admin:jobs(status, count)\nclient.admin:jobResult(jobId)\nclient.admin:cancelJob(jobId)\nclient.admin:deleteJobs(jobType, stamp)\n\n-- Tasks\nclient.admin:tasks()\nclient.admin:task(taskId)\nclient.admin:createTask(options)\nclient.admin:deleteTask(taskId)\n\n-- Misc\nclient.admin:time()\nclient.admin:shutdown(soft)\nclient.admin:compact(options)\n```\n\n### Analyzer Operations (`client.analyzer`)\n\n```lua\n-- Analyzer management\nclient.analyzer:list()\nclient.analyzer:get(name)\nclient.analyzer:exists(name)\nclient.analyzer:create(name, type, properties, features)\nclient.analyzer:delete(name, force)\n\n-- Type-specific creators\nclient.analyzer:createIdentity(name, features)\nclient.analyzer:createDelimiter(name, delimiter, features)\nclient.analyzer:createStem(name, locale, features)\nclient.analyzer:createNorm(name, locale, options, features)\nclient.analyzer:createNgram(name, options, features)\nclient.analyzer:createText(name, locale, options, features)\nclient.analyzer:createAQL(name, queryString, options, features)\nclient.analyzer:createPipeline(name, pipeline, features)\nclient.analyzer:createStopwords(name, stopwords, options, features)\nclient.analyzer:createCollation(name, locale, features)\nclient.analyzer:createGeoJSON(name, options, features)\nclient.analyzer:createGeoPoint(name, options, features)\n```\n\n### View Operations (`client.view`)\n\n```lua\n-- View management\nclient.view:list()\nclient.view:get(name)\nclient.view:properties(name)\nclient.view:exists(name)\nclient.view:drop(name)\nclient.view:rename(name, newName)\n\n-- Create views\nclient.view:create(name, type, properties)\nclient.view:createArangoSearch(name, options)\nclient.view:createSearchAlias(name, indexes)\nclient.view:createSimple(name, collection, options)\n\n-- Modify views\nclient.view:updateProperties(name, properties)\nclient.view:replaceProperties(name, properties)\n\n-- Link management (ArangoSearch)\nclient.view:addLink(viewName, collection, linkOptions)\nclient.view:removeLink(viewName, collection)\nclient.view:updateLink(viewName, collection, linkOptions)\n\n-- Index management (search-alias)\nclient.view:addIndex(viewName, collection, indexName)\nclient.view:removeIndex(viewName, collection, indexName)\n```\n\n### Foxx Operations (`client.foxx`)\n\n```lua\n-- Service management\nclient.foxx:list(excludeSystem)\nclient.foxx:get(mount)\nclient.foxx:exists(mount)\nclient.foxx:installFromUrl(mount, source, options)\nclient.foxx:installFromPath(mount, path, options)\nclient.foxx:installFromZip(mount, zipData, options)\nclient.foxx:replace(mount, source, options)\nclient.foxx:upgrade(mount, source, options)\nclient.foxx:uninstall(mount, options)\n\n-- Configuration\nclient.foxx:getConfiguration(mount)\nclient.foxx:updateConfiguration(mount, configuration)\nclient.foxx:replaceConfiguration(mount, configuration)\n\n-- Dependencies\nclient.foxx:getDependencies(mount)\nclient.foxx:updateDependencies(mount, dependencies)\nclient.foxx:replaceDependencies(mount, dependencies)\n\n-- Development mode\nclient.foxx:enableDevelopment(mount)\nclient.foxx:disableDevelopment(mount)\n\n-- Scripts\nclient.foxx:listScripts(mount)\nclient.foxx:runScript(mount, scriptName, args)\n\n-- Other\nclient.foxx:readme(mount)\nclient.foxx:swagger(mount)\nclient.foxx:download(mount)\nclient.foxx:runTests(mount, options)\n```\n\n### Embeddings (`arangodb.Embeddings`)\n\nThe Embeddings module provides vector embedding generation via OpenAI-compatible APIs (OpenAI, Ollama, vLLM, LocalAI, etc.). This is a standalone client that can be used independently of the ArangoDB connection.\n\n```lua\nlocal arangodb = require(\"arangodb\")\n\n-- Create embeddings client (uses OPENAI_API_KEY env var by default)\nlocal embeddings = arangodb.Embeddings.new({\n    api_key = \"sk-...\",                    -- Optional if OPENAI_API_KEY env var is set\n    base_url = \"https://api.openai.com/v1\", -- Default\n    model = \"text-embedding-3-small\",       -- Default\n    dimensions = 256,                       -- Optional: reduce dimensions (supported models only)\n    timeout = 30000,                        -- Request timeout in ms\n    ssl_verify = false                      -- SSL verification (default: false)\n})\n\n-- Generate single embedding\nlocal vector = embeddings:create(\"Hello world\")\n-- Returns: {0.023, -0.041, 0.012, ...} (1536 dimensions for text-embedding-3-small)\n\n-- Generate batch embeddings (more efficient for multiple texts)\nlocal vectors = embeddings:createBatch({\"Hello\", \"World\", \"Test\"})\n-- Returns: {{...}, {...}, {...}}\n\n-- Get embedding with metadata (usage stats)\nlocal result = embeddings:createWithMetadata(\"Hello world\")\n-- Returns: {\n--   embeddings = {{index=0, embedding={...}}},\n--   model = \"text-embedding-3-small\",\n--   usage = {prompt_tokens=2, total_tokens=2}\n-- }\n\n-- Get embedding dimension for current model\nlocal dim = embeddings:getDimension()\n-- Returns: 1536 (for text-embedding-3-small)\n\n-- List available embedding models (OpenAI only)\nlocal models = embeddings:listModels()\n```\n\n**Using with Ollama or other local providers:**\n\n```lua\nlocal embeddings = arangodb.Embeddings.new({\n    base_url = \"http://localhost:11434/v1\",\n    model = \"nomic-embed-text\",\n    api_key = \"ollama\"  -- Ollama doesn't require a real API key\n})\n\nlocal vector = embeddings:create(\"Search query\")\n```\n\n**Complete Vector Search Workflow:**\n\n```lua\nlocal arangodb = require(\"arangodb\")\n\n-- 1. Create ArangoDB client\nlocal client = arangodb.new({\n    endpoint = \"http://localhost:8529\",\n    username = \"root\",\n    password = \"password\"\n})\n\n-- 2. Create embeddings client\nlocal embeddings = arangodb.Embeddings.new()\n\n-- 3. Store documents with embeddings\nlocal texts = {\"Document about cats\", \"Document about dogs\", \"Document about birds\"}\nfor i, text in ipairs(texts) do\n    local vector = embeddings:create(text)\n    client.document:create(\"documents\", {\n        text = text,\n        embedding = vector\n    })\nend\n\n-- 4. Create vector index (after documents exist)\nclient.index:createVector(\"documents\", \"embedding\", {\n    metric = \"cosine\",\n    dimension = 1536,\n    nLists = 1  -- Small value for few documents\n})\n\n-- 5. Semantic search\nlocal query_vector = embeddings:create(\"Tell me about felines\")\nlocal results = client.query:execute([[\n    FOR doc IN documents\n      SORT APPROX_NEAR_COSINE(doc.embedding, @query) DESC\n      LIMIT 5\n      RETURN doc.text\n]], { query = query_vector })\n```\n\n## Testing with Docker/Podman\n\nThe project includes a docker-compose setup for testing. ArangoDB is configured with `--experimental-vector-index=true` to enable vector search features.\n\n```shell\n# Start ArangoDB and OpenResty\npodman-compose up -d\n# or\ndocker-compose up -d\n\n# Run tests via HTTP\ncurl http://localhost:8080/test\n\n# Test specific module\ncurl http://localhost:8080/test/database\ncurl http://localhost:8080/test/collection\ncurl http://localhost:8080/test/document\ncurl http://localhost:8080/test/query\ncurl http://localhost:8080/test/graph\n\n# Interactive AQL query\ncurl -X POST http://localhost:8080/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\": \"FOR i IN 1..10 RETURN i\"}'\n```\n\n### Hurl Tests\n\nThe project includes comprehensive Hurl tests in `tests/hurl/`:\n\n```shell\n# Run all Hurl tests\nhurl --test tests/hurl/*.hurl\n\n# Run specific test\nhurl --test tests/hurl/01-database.hurl\n```\n\n### DNS Resolver Note\n\nThe nginx configuration uses a DNS resolver for container networking. If switching between Docker and Podman, you may need to update `nginx/conf/nginx.conf`:\n\n- **Docker**: `resolver 127.0.0.11 ipv6=off;`\n- **Podman**: `resolver 10.89.0.1 ipv6=off;` (check with `podman exec \u003ccontainer\u003e cat /etc/resolv.conf`)\n\n## Testing with resty\n\n```shell\n# Run the test script\nresty -I src src/test.lua\n```\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskitsanos%2Flua-arangodb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskitsanos%2Flua-arangodb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskitsanos%2Flua-arangodb/lists"}