JavaScript client
The Lucenia Node.js client (@lucenia/client) lets you talk to a Lucenia cluster from JavaScript or TypeScript instead of building raw HTTP requests. It is derived from the OpenSearch JavaScript client, ships its own TypeScript definitions, and includes helpers for bulk indexing, multi-search, and scrolling.
Compatibility
The client requires Node.js 14 or later. The npm package version tracks the Lucenia server version: client 0.12.x is intended for use with Lucenia 0.12.x clusters.
Installation
Install the client from npm:
npm install @lucenia/client
For production projects, pin the minor version in package.json:
{
"dependencies": {
"@lucenia/client": "~0.12.1"
}
}
Then import the client. In CommonJS:
const { Client } = require('@lucenia/client');
Or as an ES module:
import { Client } from '@lucenia/client';
Creating a client
Connecting to a secured cluster
The default Lucenia configuration runs with TLS and basic authentication enabled. The snippet below creates a client suitable for local development against a cluster using self-signed certificates. Configure a real CA bundle and enable certificate verification in production.
const { Client } = require('@lucenia/client');
const client = new Client({
node: 'https://localhost:9200',
auth: {
username: 'admin',
password: 'MyStrongPassword123!',
},
ssl: {
rejectUnauthorized: false,
},
});
const info = await client.info();
console.log(`Connected to ${info.body.version.distribution} ${info.body.version.number}`);
rejectUnauthorized: false disables TLS verification and should only be used for local development. In production, supply your cluster's CA certificate instead.
To verify certificates, pass a CA bundle:
const fs = require('fs');
const { Client } = require('@lucenia/client');
const client = new Client({
node: 'https://localhost:9200',
auth: {
username: 'admin',
password: 'MyStrongPassword123!',
},
ssl: {
ca: fs.readFileSync('/path/to/root-ca.pem'),
},
});
Authenticating with an API key
Lucenia 0.12 and later can authenticate requests with a native, revocable API key. Pass the api_key value returned when the key is created — it is already base64 encoded, so do not encode it again. Always use HTTPS when sending an API key.
const client = new Client({
node: 'https://localhost:9200',
auth: {
apiKey: process.env.LUCENIA_API_KEY,
},
});
Connecting to an unsecured cluster
For development clusters running without TLS or authentication:
const client = new Client({ node: 'http://localhost:9200' });
Working with documents
Every API call resolves to a response object whose payload is on .body.
Creating an index
Create an index with custom settings and mappings:
const indexName = 'my-index';
const response = await client.indices.create({
index: indexName,
body: {
settings: {
index: {
number_of_shards: 1,
number_of_replicas: 0,
},
},
mappings: {
properties: {
title: { type: 'text' },
text: { type: 'text' },
year: { type: 'integer' },
},
},
},
});
console.log(`Index created: ${response.body.acknowledged}`);
Indexing a single document
const response = await client.index({
index: indexName,
id: '1',
body: {
title: 'Introduction to Lucenia',
text: 'Lucenia is a high-performance search engine.',
year: 2025,
},
refresh: true,
});
console.log(response.body.result);
Bulk indexing
For higher throughput, use the helpers.bulk helper. It batches documents, retries failures, and returns statistics rather than a raw bulk response. onDocument decides the action for each document, and refreshOnCompletion makes the new documents searchable when the run finishes:
const documents = [
{ title: 'Getting Started', text: 'Use the @lucenia/client package.', year: 2025 },
{ title: 'Search Features', text: 'Full-text search and more.', year: 2025 },
{ title: 'Bulk Operations', text: 'Index many docs at once.', year: 2025 },
];
const stats = await client.helpers.bulk({
datasource: documents,
onDocument() {
return { index: { _index: indexName } };
},
refreshOnCompletion: true,
});
console.log(`Indexed ${stats.successful} documents (failed: ${stats.failed})`);
datasource also accepts a stream or an async iterator, so you can index a large file without holding it in memory.
Searching
Run a match query against a specific field:
const response = await client.search({
index: indexName,
body: {
query: {
match: { title: 'Lucenia' },
},
},
});
console.log(`Found ${response.body.hits.total.value} documents:`);
for (const hit of response.body.hits.hits) {
console.log(` [${hit._id}] score=${hit._score} ${hit._source.title}`);
}
Run a multi_match query that boosts matches in the title field:
const response = await client.search({
index: indexName,
body: {
query: {
multi_match: {
query: 'search',
fields: ['title^2', 'text'],
},
},
},
});
For pagination, sorting, point-in-time, and scroll search, see the Query DSL documentation. The client also exposes helpers.scrollSearch and helpers.scrollDocuments for iterating large result sets.
Deleting a document and the index
await client.delete({ index: indexName, id: '1' });
await client.indices.delete({ index: indexName });
TypeScript
The package ships its own type definitions, so no @types package is needed:
import { Client } from '@lucenia/client';
interface Book {
title: string;
year: number;
}
const client = new Client({ node: 'https://localhost:9200' });
const response = await client.search<Book>({
index: 'my-index',
body: { query: { match_all: {} } },
});
Authenticating with AWS SigV4
For a managed cluster that authenticates with AWS Signature V4, use the signer exported from the aws subpath (aws-v3 for the AWS SDK v3):
const { Client } = require('@lucenia/client');
const { AwsSigv4Signer } = require('@lucenia/client/aws');
Next steps
The client supports a wider set of features beyond the basics covered here, including:
- Bulk indexing helpers with configurable concurrency and retries
- Multi-search (
helpers.msearch) - Scroll and point-in-time search helpers
- AWS SigV4 request signing
- Long numeral support for values that exceed JavaScript's safe integer range
- Connection pooling, sniffing, and custom transports