π Integrating AWS OpenSearch in a Next.js App
Hamza Khan
Posted on October 28, 2024
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
- AWS Account with OpenSearch Service access.
- Next.js project set up.
- Basic familiarity with REST APIs and JSON.
π Step 1: Setting Up AWS OpenSearch
- Go to the AWS Management Console.
- Navigate to OpenSearch Service and click Create Domain.
- 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.
- 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
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(),
});
Add AWS credentials to .env.local
:
AWS_ACCESS_KEY=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-access-key
π 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' });
}
}
π 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' });
}
}
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,
}),
});
π 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' });
}
}
π 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>
);
}
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.
Posted on October 28, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.