arango-aggregate
v1.0.0
Published
A declarative, chainable query builder for ArangoDB built on top of `arangojs`.
Readme
arango-aggregate
A declarative, chainable query builder for ArangoDB built on top of arangojs.
arango-aggregate is designed to reduce raw AQL usage, support config-driven queries, and handle complex operations like joins, pagination, and ArangoSearch with a minimal, expressive API. It is ideal for dynamic backends and automation-heavy systems.
Features
- Chainable API:
filter→sort→paginate→execute. - Collection Support: Works with both standard and edge collections.
- Joins:
INNERandLEFTjoins via a simplifiedpopulatemethod. - ArangoSearch: Built-in support for search views.
- Pagination: Supports both Keyset (Seek) and Offset pagination.
- Bulk Operations: Fluent interface for
patchandremove. - Config-Driven: Execute complex queries using plain JSON objects.
- Projections: Field-level selection for both main documents and joined data.
- Zero Schema Coupling: No models required; works directly with your collections.
Installation
npm install arango-aggregateBasic Usage
import { Database } from "arangojs";
import { arangosh } from "arango-aggregate";
const db = new Database({
url: "http://localhost:8529",
databaseName: "mydb",
});
const users = new arangosh(db, "users");
const result = await users
.filter("status", "==", "active")
.sort("createdAt", "DESC")
.paginate(10, 0)
.execute();Querying
Filters
.filter("region", "==", "NA")
.filter("points", ">", 100)Supported operators: ==, !=, >, >=, <, <=, IN, NOT IN.
Sorting
.sort("points", "DESC")Pagination
Offset Pagination
.paginate(10, 20) // limit 10, offset 20Keyset Pagination (Seek) Useful for large datasets to avoid performance degradation.
.sort("_key", "ASC")
.paginate(10, lastKey)Field Projection (Select)
// Top-level fields
.select(["qty", "total", "customer"])
// Nested populate fields
.populate("_from", "customers", "customer", true, ["name", "region"])Mutations
Insert
await users.create({
name: "John",
tier: "VIP",
points: 50,
});Bulk Update (Patch)
await users.filter("region", "==", "EU").patch({ region: "EU-1" });Bulk Remove
await users.filter("status", "==", "inactive").remove();Advanced Features
ArangoSearch
Leverage ArangoSearch views internally.
await new arangosh(db, "products")
.search("inventory_search_view", "gaming OR laptop")
.execute();Populate (Joins)
INNER JOIN (Strict) Drops dangling edges where the reference does not exist.
.populate("_to", "inventory", "product", true)LEFT JOIN (Non-Strict)
Keeps dangling edges; the populated field becomes null.
.populate("_to", "inventory", "product", false)Multiple Populates
.populate("_from", "customers", "customer", true)
.populate("_to", "inventory", "product", true)Config-Driven Queries
You can generate the same complex queries using a JSON configuration, making it perfect for dynamic frontends or API-driven query generation.
const config = {
filters: [{ field: "status", operator: "==", value: "completed" }],
sort: { field: "total", dir: "DESC" },
paginate: { limit: 5, offset: 0 },
populates: [
{
field: "_from",
targetCollection: "customers",
alias: "customer",
strict: true,
returnFields: ["name"],
},
],
select: ["total", "customer"],
};
await new arangosh(db, "orders").applyConfig(config).execute();Design Philosophy
- Declarative over imperative: Describe what you want, not how to write the AQL.
- AQL generated, not handwritten: Reduces syntax errors and injection risks.
- Minimal app-level conditionals: Handle logic via chainable methods.
- Database does the heavy lifting: Optimized for ArangoDB's native performance.
Requirements
- Node.js: ≥ 18
- ArangoDB: ≥ 3.10
- arangojs: ≥ 10
Status
- 🧪 Actively tested
- 🚀 Production-ready core
- 🔧 API stable, extensions welcome
License
MIT
99ae4a374906c26690762bd9c3f86780d41ad3a4e200ab35fe92b39783feafae 7cc4c5453b4aa48c0d2414fd224663ee75f67e3f40309c193a462dea755f1235 153ea70e85f9e33f7a51e8ee955268ce9b1e86b61f8f73c29618361f987edbbf ca319b84e5d70ac8bde7f86635ea1be248dc9aea55699a4b1754e4edf538532d aa3ce3d4f2453c9f8957d8193648fdfb7a528afbf9e8e433690f11c735dc88c4
