NestJS OpenSearch Module

1.4.1 · active · verified Sun Apr 19

The `nestjs-opensearch` package provides a dedicated module for integrating OpenSearch with the NestJS framework. It simplifies connecting to OpenSearch clusters, offering configurations for single, multiple, and asynchronously provisioned clients. The current stable version is 1.4.1, which includes support for NestJS v11 and OpenSearch client v3. Releases tend to align with major NestJS and `@opensearch-project/opensearch` peer dependency updates to maintain compatibility. Its key differentiators include leveraging NestJS's declarative module structure, providing robust dependency injection for OpenSearch clients (both default and named), and supporting both synchronous and asynchronous configuration patterns, including `useFactory` and `useClass` options. This design allows for flexible integration within various NestJS application architectures, adhering to the framework's modularity and inversion of control principles.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to configure default and named OpenSearch clients asynchronously using `ConfigModule` and `useFactory`. It then shows how to inject these clients into a service (`SearchService`) to perform basic indexing and searching operations, illustrating a typical NestJS integration pattern.

import { Module, Injectable } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { OpensearchModule, InjectOpensearchClient, OpensearchClient } from 'nestjs-opensearch';

// A basic configuration factory for NestJS ConfigModule
function configuration() {
  return {
    opensearch: {
      node: process.env.OPENSEARCH_NODE || 'http://localhost:9200',
      auth: {
        username: process.env.OPENSEARCH_USERNAME || 'admin',
        password: process.env.OPENSEARCH_PASSWORD || 'admin'
      }
    }
  };
}

@Injectable()
export class SearchService {
  constructor(
    // Inject the default client (no clientName specified)
    @InjectOpensearchClient() private readonly defaultClient: OpensearchClient,
    // Inject a named client
    @InjectOpensearchClient('myNamedClient') private readonly namedClient: OpensearchClient,
  ) {}

  async indexDocument(index: string, id: string, document: any): Promise<void> {
    await this.defaultClient.index({
      index,
      id,
      body: document,
      refresh: true,
    });
    console.log(`Document '${id}' indexed successfully using the default client.`);
  }

  async searchDocuments(index: string, query: any): Promise<any[]> {
    const { body } = await this.namedClient.search({
      index,
      body: { query },
    });
    console.log(`Search performed on '${index}' using 'myNamedClient'.`);
    return body.hits.hits;
  }
}

@Module({
  imports: [
    // Load configuration for the application
    ConfigModule.forRoot({
      load: [configuration],
      isGlobal: true,
    }),
    // Configure the default OpenSearch client asynchronously
    OpensearchModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        node: configService.get<string>('opensearch.node'),
        auth: configService.get<{ username: string; password: string }>('opensearch.auth'),
      }),
    }),
    // Configure a named OpenSearch client asynchronously
    OpensearchModule.forRootAsync({
      clientName: 'myNamedClient',
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        node: configService.get<string>('opensearch.node'),
        auth: configService.get<{ username: string; password: string }>('opensearch.auth'),
      }),
    }),
  ],
  providers: [SearchService],
  exports: [SearchService],
})
export class AppModule {}

// To bootstrap and run this application:
// import { NestFactory } from '@nestjs/core';
// async function bootstrap() {
//   const app = await NestFactory.create(AppModule);
//   await app.listen(3000);
//   const searchService = app.get(SearchService);
//   await searchService.indexDocument('my-test-index', 'doc1', { title: 'Hello World' });
//   const results = await searchService.searchDocuments('my-test-index', { match_all: {} });
//   console.log('Search results:', results);
// }
// bootstrap();

view raw JSON →