DEV Community

Hamza Khan
Hamza Khan

Posted on

3

๐Ÿ” 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.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where youโ€™ll build it, break it, debug it, and fix it. Youโ€™ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good olโ€™ AI to find and fix issues fast.

RSVP here โ†’

Top comments (0)

Cloudinary image

Video API: manage, encode, and optimize for any device, channel or network condition. Deliver branded video experiences in minutes and get deep engagement insights.

Learn more

๐Ÿ‘‹ Kindness is contagious

Please leave a โค๏ธ or a friendly comment on this post if you found it helpful!

Okay