DEV Community

Hamza Khan
Hamza Khan

Posted on

πŸ” Integrating AWS OpenSearch in a Next.js App

Adding a robust search feature can greatly enhance your app’s user experience, and AWS OpenSearch (formerly known as ElasticSearch) provides powerful search and analytics capabilities. In this guide, we’ll explore how to integrate AWS OpenSearch with a Next.js application to add fast, scalable search functionality.

πŸ›  Prerequisites

  1. AWS Account with OpenSearch Service access.
  2. Next.js project set up.
  3. Basic familiarity with REST APIs and JSON.

πŸš€ Step 1: Setting Up AWS OpenSearch

  1. Go to the AWS Management Console.
  2. Navigate to OpenSearch Service and click Create Domain.
  3. Configure:
    • Domain Name: Provide a unique name for your OpenSearch cluster.
    • Instance Type: Choose an appropriate instance type for development (e.g., t2.small).
    • Access Policy: Set access policies that allow access from your Next.js app’s IP or specific AWS roles.
  4. Click Create and wait for the domain to initialize.

πŸš€ Step 2: Configuring OpenSearch Client in Next.js

Once AWS OpenSearch is ready, use the AWS SDK and @opensearch-project/opensearch package to connect and make queries.

1. Install the AWS SDK and OpenSearch Client

npm install aws-sdk @opensearch-project/opensearch
Enter fullscreen mode Exit fullscreen mode

2. Set Up OpenSearch Client in Next.js

Create a new file lib/opensearchClient.js for initializing and configuring the client:

import AWS from 'aws-sdk';
import { Client } from '@opensearch-project/opensearch';

const region = 'your-aws-region';
const domainEndpoint = 'https://your-opensearch-domain-endpoint';

// Configure AWS credentials
AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region,
});

// Set up OpenSearch client
export const opensearchClient = new Client({
  node: domainEndpoint,
  Connection: require('@opensearch-project/opensearch/aws'),
  awsConfig: new AWS.Config(),
});
Enter fullscreen mode Exit fullscreen mode

Add AWS credentials to .env.local:

AWS_ACCESS_KEY=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-access-key
Enter fullscreen mode Exit fullscreen mode

πŸš€ Step 3: Creating an Index in OpenSearch

To add data, create an index to structure and store documents.

1. API Route to Create an Index

In pages/api/createIndex.js:

import { opensearchClient } from '../../lib/opensearchClient';

export default async function handler(req, res) {
  try {
    await opensearchClient.indices.create({
      index: 'products',
      body: {
        mappings: {
          properties: {
            name: { type: 'text' },
            description: { type: 'text' },
            price: { type: 'float' },
          },
        },
      },
    });
    res.status(200).json({ message: 'Index created successfully' });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Error creating index' });
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Step 4: Adding Data to the OpenSearch Index

Add documents (data) to your products index to make it searchable.

1. API Route to Add Documents

In pages/api/addDocument.js:

import { opensearchClient } from '../../lib/opensearchClient';

export default async function handler(req, res) {
  const { name, description, price } = req.body;

  try {
    await opensearchClient.index({
      index: 'products',
      body: { name, description, price },
    });
    res.status(200).json({ message: 'Document added successfully' });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Error adding document' });
  }
}
Enter fullscreen mode Exit fullscreen mode

Test this API by calling it with sample data:

fetch('/api/addDocument', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Product Name',
    description: 'Description of the product',
    price: 29.99,
  }),
});
Enter fullscreen mode Exit fullscreen mode

πŸš€ Step 5: Implementing the Search Feature

Set up a search route to query OpenSearch and return matching results to the user.

1. API Route for Searching

In pages/api/search.js:

import { opensearchClient } from '../../lib/opensearchClient';

export default async function handler(req, res) {
  const { query } = req.query;

  try {
    const { body } = await opensearchClient.search({
      index: 'products',
      body: {
        query: {
          multi_match: {
            query,
            fields: ['name', 'description'],
          },
        },
      },
    });
    const results = body.hits.hits.map(hit => hit._source);
    res.status(200).json({ results });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Error executing search' });
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Step 6: Integrating Search into the UI

Let’s add a simple search component in components/Search.js to display search results.

import { useState } from 'react';

export default function Search() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  const handleSearch = async () => {
    const res = await fetch(`/api/search?query=${query}`);
    const data = await res.json();
    setResults(data.results);
  };

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search for products..."
      />
      <button onClick={handleSearch}>Search</button>

      <ul>
        {results.map((result, index) => (
          <li key={index}>
            <h3>{result.name}</h3>
            <p>{result.description}</p>
            <p>${result.price}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Add the Search component to a page, such as pages/index.js, to test it.

πŸš€ Performance Metrics: Testing and Tuning OpenSearch

With OpenSearch, you can fine-tune performance by optimizing:

  • Indexing strategy: Split data into multiple indexes based on usage.
  • Query optimization: Use filters instead of matches for faster, cache-friendly queries.
  • Scaling nodes: AWS allows scaling OpenSearch clusters up or down based on traffic.

Top comments (0)