Kuasai Elasticsearch dari konsep inti hingga produksi. Pelajari indexing, querying, aggregations, dan bangun platform e-commerce search lengkap dengan NestJS featuring full-text search, filters, dan analytics.

Aplikasi modern memerlukan powerful search capabilities. Users expect instant results, typo tolerance, dan relevant filtering. Traditional SQL databases struggle dengan full-text search at scale. Elasticsearch menyelesaikan ini dengan menyediakan distributed search dan analytics engine yang dibangun di atas Apache Lucene.
Digunakan oleh companies seperti Netflix, Uber, dan Shopify, Elasticsearch power search di billions dari documents. Ini bukan hanya search engine—ini adalah real-time analytics platform yang enable complex aggregations, geospatial queries, dan machine learning-powered insights.
Dalam artikel ini, kita akan mengeksplorasi arsitektur Elasticsearch, memahami setiap core concept dari indexing hingga aggregations, dan membangun production-ready e-commerce search platform dengan NestJS yang mendemonstrasikan full-text search, filtering, faceting, dan real-time analytics.
Traditional relational databases memiliki limitations untuk search:
Poor Full-Text Search: SQL LIKE queries lambat dan inflexible. Tidak ada relevance ranking.
No Typo Tolerance: "Elasticsearch" return tidak ada results daripada "Elasticsearch".
Slow Aggregations: Complex GROUP BY queries di large datasets lambat.
Limited Filtering: Combining multiple filters memerlukan complex SQL logic.
No Real-Time Analytics: Aggregations memerlukan batch processing.
Elasticsearch dibangun untuk search dan analytics:
Powerful Full-Text Search: Relevance ranking, fuzzy matching, phrase queries.
Typo Tolerance: Fuzzy queries find similar terms.
Fast Aggregations: Real-time analytics di billions dari documents.
Flexible Filtering: Combine multiple filters efficiently.
Real-Time Analytics: Instant aggregations dan insights.
Distributed: Scale horizontally di multiple nodes.
Index: Collection dari documents dengan similar characteristics. Similar dengan database table.
Document: Single record dengan fields. Similar dengan database row. Stored sebagai JSON.
Field: Individual piece dari data dalam document. Similar dengan column.
Mapping: Schema definition untuk index. Define field types dan analyzers.
Shard: Partition dari index. Enable horizontal scaling.
Replica: Copy dari shard untuk fault tolerance dan read scaling.
Node: Single Elasticsearch instance.
Cluster: Collection dari nodes yang work together.
Document → Analyzer → Inverted Index → Query → Scoring → ResultsCore data structure yang membuat Elasticsearch cepat:
Document 1: "Elasticsearch is powerful"
Document 2: "Elasticsearch is fast"
Inverted Index:
elasticsearch → [1, 2]
is → [1, 2]
powerful → [1]
fast → [2]
Query: "elasticsearch"
Result: [1, 2] (instant lookup)Indexing adalah process dari adding documents ke Elasticsearch.
Index Creation:
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": { "type": "text" },
"price": { "type": "float" },
"category": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}Document Indexing:
POST /products/_doc
{
"name": "Wireless Headphones",
"price": 99.99,
"category": "electronics",
"created_at": "2026-02-24"
}Bulk Indexing:
POST /_bulk
{ "index": { "_index": "products" } }
{ "name": "Product 1", "price": 10 }
{ "index": { "_index": "products" } }
{ "name": "Product 2", "price": 20 }Use Cases:
Mapping define bagaimana documents diindex dan di-search.
Field Types:
# Text - analyzed untuk full-text search
"name": { "type": "text" }
# Keyword - exact matching, tidak analyzed
"category": { "type": "keyword" }
# Numeric - numbers
"price": { "type": "float" }
# Date - timestamps
"created_at": { "type": "date" }
# Geo - geographic coordinates
"location": { "type": "geo_point" }
# Nested - complex objects
"reviews": { "type": "nested" }Analyzers:
Analyzers tokenize dan normalize text:
PUT /products
{
"settings": {
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "stop"]
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "custom_analyzer"
}
}
}
}Use Cases:
Elasticsearch provide powerful query DSL.
Match Query - Full-text search dengan relevance:
GET /products/_search
{
"query": {
"match": {
"name": "wireless headphones"
}
}
}Bool Query - Combine multiple queries:
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "headphones" } }
],
"filter": [
{ "range": { "price": { "lte": 100 } } }
],
"must_not": [
{ "term": { "category": "discontinued" } }
]
}
}
}Range Query - Filter by range:
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 50,
"lte": 200
}
}
}
}Fuzzy Query - Typo tolerance:
GET /products/_search
{
"query": {
"fuzzy": {
"name": {
"value": "elasticsearch",
"fuzziness": "AUTO"
}
}
}
}Use Cases:
Aggregations enable real-time analytics.
Terms Aggregation - Count by category:
GET /products/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category",
"size": 10
}
}
}
}Range Aggregation - Group by price range:
GET /products/_search
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 50 },
{ "from": 50, "to": 100 },
{ "from": 100 }
]
}
}
}
}Date Histogram - Trends over time:
GET /products/_search
{
"size": 0,
"aggs": {
"sales_over_time": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "month"
}
}
}
}Nested Aggregation - Multi-level analytics:
GET /products/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}Use Cases:
Elasticsearch score documents by relevance menggunakan TF-IDF dan BM25.
TF-IDF (Term Frequency - Inverse Document Frequency):
Score = TF(term) × IDF(term)
TF: How often term appear di document
IDF: How rare term adalah di semua documentsBM25 (Better Matching 25):
Modern algorithm yang improve di TF-IDF:
# Elasticsearch gunakan BM25 by default
# Configurable parameters:
# k1: Controls term frequency saturation (default: 1.2)
# b: Controls field length normalization (default: 0.75)
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"similarity": "BM25"
}
}
}
}Boosting:
Increase relevance dari certain fields:
GET /products/_search
{
"query": {
"multi_match": {
"query": "wireless headphones",
"fields": [
"name^3", # Boost name 3x
"description^2", # Boost description 2x
"tags" # Normal weight
]
}
}
}Use Cases:
Important distinction untuk performance:
Query - Calculate relevance score (slower):
{ "match": { "name": "headphones" } }Filter - Yes/no match, tidak ada scoring (faster):
{ "term": { "category": "electronics" } }Best Practice:
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "headphones" } } # Query - scored
],
"filter": [
{ "range": { "price": { "lte": 100 } } } # Filter - fast
]
}
}
}Efficient pagination untuk large result sets:
Offset-Based Pagination:
GET /products/_search
{
"from": 20,
"size": 10,
"query": { "match_all": {} }
}Search After - Better untuk large offsets:
GET /products/_search
{
"size": 10,
"query": { "match_all": {} },
"sort": [{ "created_at": "desc" }],
"search_after": ["2026-02-24T10:00:00"]
}Sorting:
GET /products/_search
{
"query": { "match": { "name": "headphones" } },
"sort": [
{ "price": "asc" },
{ "_score": "desc" }
]
}Show matched terms di results:
GET /products/_search
{
"query": { "match": { "description": "wireless" } },
"highlight": {
"fields": {
"description": {}
}
}
}Provide search suggestions:
GET /products/_search
{
"suggest": {
"product-suggest": {
"prefix": "wire",
"completion": {
"field": "name.completion"
}
}
}
}Index Optimization:
PUT /products
{
"settings": {
"number_of_shards": 3, # Parallelism
"number_of_replicas": 1, # Redundancy
"refresh_interval": "30s" # Batch updates
}
}Query Optimization:
# Gunakan filter daripada query ketika possible
# Gunakan bool queries efficiently
# Avoid expensive operations (wildcard, regex)
# Gunakan appropriate field typesSekarang mari kita bangun production-ready e-commerce search platform yang mendemonstrasikan Elasticsearch patterns. Sistem handle:
npm i -g @nestjs/cli
nest new ecommerce-search-platform
cd ecommerce-search-platform
npm install @nestjs/elasticsearch @elastic/elasticsearch class-validator class-transformerimport { Module } from '@nestjs/common';
import { ElasticsearchModule } from '@nestjs/elasticsearch';
import { ElasticsearchService } from './elasticsearch.service';
@Module({
imports: [
ElasticsearchModule.register({
node: process.env.ELASTICSEARCH_URL || 'http://localhost:9200',
}),
],
providers: [ElasticsearchService],
exports: [ElasticsearchService],
})
export class EsModule {}import { Injectable, OnModuleInit } from '@nestjs/common';
import { ElasticsearchService as NestElasticsearchService } from '@nestjs/elasticsearch';
@Injectable()
export class ElasticsearchService implements OnModuleInit {
constructor(private readonly elasticsearchService: NestElasticsearchService) {}
async onModuleInit() {
await this.createProductIndex();
}
private async createProductIndex() {
const indexName = 'products';
try {
const indexExists = await this.elasticsearchService.indices.exists({
index: indexName,
});
if (!indexExists) {
await this.elasticsearchService.indices.create({
index: indexName,
body: {
settings: {
number_of_shards: 3,
number_of_replicas: 1,
analysis: {
analyzer: {
custom_analyzer: {
type: 'custom',
tokenizer: 'standard',
filter: ['lowercase', 'stop'],
},
},
},
},
mappings: {
properties: {
id: { type: 'keyword' },
name: {
type: 'text',
analyzer: 'custom_analyzer',
fields: {
keyword: { type: 'keyword' },
completion: { type: 'completion' },
},
},
description: {
type: 'text',
analyzer: 'custom_analyzer',
},
price: { type: 'float' },
category: { type: 'keyword' },
tags: { type: 'keyword' },
rating: { type: 'float' },
reviews_count: { type: 'integer' },
in_stock: { type: 'boolean' },
created_at: { type: 'date' },
updated_at: { type: 'date' },
},
},
},
});
console.log(`Index ${indexName} created successfully`);
}
} catch (error) {
console.error('Error creating index:', error);
}
}
async indexProduct(product: any) {
return this.elasticsearchService.index({
index: 'products',
id: product.id,
body: product,
});
}
async indexBulkProducts(products: any[]) {
const body = products.flatMap((product) => [
{ index: { _index: 'products', _id: product.id } },
product,
]);
return this.elasticsearchService.bulk({ body });
}
async searchProducts(query: string, filters: any = {}, page: number = 1, limit: number = 10) {
const from = (page - 1) * limit;
const searchBody: any = {
from,
size: limit,
query: {
bool: {
must: [
{
multi_match: {
query,
fields: ['name^3', 'description^2', 'tags'],
fuzziness: 'AUTO',
},
},
],
filter: [],
},
},
};
// Add filters
if (filters.category) {
searchBody.query.bool.filter.push({
term: { category: filters.category },
});
}
if (filters.minPrice || filters.maxPrice) {
const rangeFilter: any = {};
if (filters.minPrice) rangeFilter.gte = filters.minPrice;
if (filters.maxPrice) rangeFilter.lte = filters.maxPrice;
searchBody.query.bool.filter.push({
range: { price: rangeFilter },
});
}
if (filters.inStock !== undefined) {
searchBody.query.bool.filter.push({
term: { in_stock: filters.inStock },
});
}
if (filters.minRating) {
searchBody.query.bool.filter.push({
range: { rating: { gte: filters.minRating } },
});
}
const results = await this.elasticsearchService.search({
index: 'products',
body: searchBody,
});
return {
total: results.hits.total.value,
page,
limit,
results: results.hits.hits.map((hit: any) => ({
id: hit._id,
score: hit._score,
...hit._source,
})),
};
}
async getProductFacets() {
const results = await this.elasticsearchService.search({
index: 'products',
body: {
size: 0,
aggs: {
categories: {
terms: {
field: 'category',
size: 20,
},
},
price_ranges: {
range: {
field: 'price',
ranges: [
{ to: 50 },
{ from: 50, to: 100 },
{ from: 100, to: 200 },
{ from: 200 },
],
},
},
rating_distribution: {
terms: {
field: 'rating',
size: 5,
},
},
},
},
});
return {
categories: results.aggregations.categories.buckets,
priceRanges: results.aggregations.price_ranges.buckets,
ratings: results.aggregations.rating_distribution.buckets,
};
}
async getProductSuggestions(prefix: string) {
const results = await this.elasticsearchService.search({
index: 'products',
body: {
suggest: {
product_suggest: {
prefix,
completion: {
field: 'name.completion',
size: 10,
skip_duplicates: true,
},
},
},
},
});
return results.suggest.product_suggest[0].options.map((option: any) => ({
text: option.text,
score: option._score,
}));
}
async getProductById(id: string) {
const result = await this.elasticsearchService.get({
index: 'products',
id,
});
return {
id: result._id,
...result._source,
};
}
async deleteProduct(id: string) {
return this.elasticsearchService.delete({
index: 'products',
id,
});
}
async updateProduct(id: string, updates: any) {
return this.elasticsearchService.update({
index: 'products',
id,
body: {
doc: updates,
},
});
}
async getAnalytics() {
const results = await this.elasticsearchService.search({
index: 'products',
body: {
size: 0,
aggs: {
total_products: { value_count: { field: 'id' } },
avg_price: { avg: { field: 'price' } },
avg_rating: { avg: { field: 'rating' } },
in_stock_count: {
filter: { term: { in_stock: true } },
},
products_by_category: {
terms: {
field: 'category',
size: 10,
},
aggs: {
avg_price: { avg: { field: 'price' } },
avg_rating: { avg: { field: 'rating' } },
},
},
},
},
});
return {
totalProducts: results.aggregations.total_products.value,
avgPrice: results.aggregations.avg_price.value,
avgRating: results.aggregations.avg_rating.value,
inStockCount: results.aggregations.in_stock_count.doc_count,
byCategory: results.aggregations.products_by_category.buckets.map(
(bucket: any) => ({
category: bucket.key,
count: bucket.doc_count,
avgPrice: bucket.avg_price.value,
avgRating: bucket.avg_rating.value,
}),
),
};
}
}import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '../elasticsearch/elasticsearch.service';
@Injectable()
export class ProductsService {
constructor(private readonly elasticsearchService: ElasticsearchService) {}
async createProduct(productData: any) {
const product = {
id: `product_${Date.now()}`,
...productData,
created_at: new Date(),
updated_at: new Date(),
};
await this.elasticsearchService.indexProduct(product);
return product;
}
async createBulkProducts(products: any[]) {
const productsWithMetadata = products.map((p) => ({
id: `product_${Date.now()}_${Math.random()}`,
...p,
created_at: new Date(),
updated_at: new Date(),
}));
await this.elasticsearchService.indexBulkProducts(productsWithMetadata);
return productsWithMetadata;
}
async searchProducts(query: string, filters: any = {}, page: number = 1, limit: number = 10) {
return this.elasticsearchService.searchProducts(query, filters, page, limit);
}
async getProductById(id: string) {
return this.elasticsearchService.getProductById(id);
}
async updateProduct(id: string, updates: any) {
updates.updated_at = new Date();
return this.elasticsearchService.updateProduct(id, updates);
}
async deleteProduct(id: string) {
return this.elasticsearchService.deleteProduct(id);
}
async getFacets() {
return this.elasticsearchService.getProductFacets();
}
async getSuggestions(prefix: string) {
return this.elasticsearchService.getProductSuggestions(prefix);
}
async getAnalytics() {
return this.elasticsearchService.getAnalytics();
}
}import { Controller, Post, Get, Put, Delete, Body, Param, Query } from '@nestjs/common';
import { ProductsService } from './products.service';
@Controller('products')
export class ProductsController {
constructor(private readonly productsService: ProductsService) {}
@Post()
async createProduct(@Body() productData: any) {
const product = await this.productsService.createProduct(productData);
return {
message: 'Product created successfully',
product,
};
}
@Post('bulk')
async createBulkProducts(@Body() products: any[]) {
const created = await this.productsService.createBulkProducts(products);
return {
message: `${created.length} products created successfully`,
count: created.length,
};
}
@Get('search')
async searchProducts(
@Query('q') query: string,
@Query('category') category?: string,
@Query('minPrice') minPrice?: number,
@Query('maxPrice') maxPrice?: number,
@Query('inStock') inStock?: boolean,
@Query('minRating') minRating?: number,
@Query('page') page: number = 1,
@Query('limit') limit: number = 10,
) {
const filters = {
category,
minPrice: minPrice ? parseFloat(minPrice as any) : undefined,
maxPrice: maxPrice ? parseFloat(maxPrice as any) : undefined,
inStock: inStock ? inStock === 'true' : undefined,
minRating: minRating ? parseFloat(minRating as any) : undefined,
};
return this.productsService.searchProducts(
query,
filters,
parseInt(page as any),
parseInt(limit as any),
);
}
@Get('facets')
async getFacets() {
return this.productsService.getFacets();
}
@Get('suggestions')
async getSuggestions(@Query('prefix') prefix: string) {
return this.productsService.getSuggestions(prefix);
}
@Get('analytics')
async getAnalytics() {
return this.productsService.getAnalytics();
}
@Get(':id')
async getProduct(@Param('id') id: string) {
return this.productsService.getProductById(id);
}
@Put(':id')
async updateProduct(@Param('id') id: string, @Body() updates: any) {
await this.productsService.updateProduct(id, updates);
return {
message: 'Product updated successfully',
id,
};
}
@Delete(':id')
async deleteProduct(@Param('id') id: string) {
await this.productsService.deleteProduct(id);
return {
message: 'Product deleted successfully',
id,
};
}
}import { Module } from '@nestjs/common';
import { EsModule } from './elasticsearch/elasticsearch.module';
import { ProductsService } from './products/products.service';
import { ProductsController } from './products/products.controller';
@Module({
imports: [EsModule],
controllers: [ProductsController],
providers: [ProductsService],
})
export class AppModule {}version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.10.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- '9200:9200'
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:8.10.0
ports:
- '5601:5601'
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
volumes:
elasticsearch_data:# Start Elasticsearch dan Kibana
docker-compose up -d
# Install dependencies
npm install
# Run application
npm run start:dev
# Access Kibana
# http://localhost:5601# Buat product
curl -X POST http://localhost:3000/products \
-H "Content-Type: application/json" \
-d '{
"name": "Wireless Headphones",
"description": "High-quality wireless headphones dengan noise cancellation",
"price": 99.99,
"category": "electronics",
"tags": ["audio", "wireless", "headphones"],
"rating": 4.5,
"reviews_count": 150,
"in_stock": true
}'
# Buat bulk products
curl -X POST http://localhost:3000/products/bulk \
-H "Content-Type: application/json" \
-d '[
{
"name": "USB-C Cable",
"description": "Fast charging USB-C cable",
"price": 15.99,
"category": "accessories",
"tags": ["cable", "usb-c"],
"rating": 4.2,
"reviews_count": 300,
"in_stock": true
},
{
"name": "Phone Case",
"description": "Protective phone case",
"price": 25.99,
"category": "accessories",
"tags": ["protection", "case"],
"rating": 4.0,
"reviews_count": 200,
"in_stock": true
}
]'
# Search products
curl "http://localhost:3000/products/search?q=headphones&page=1&limit=10"
# Search dengan filters
curl "http://localhost:3000/products/search?q=wireless&category=electronics&maxPrice=150&minRating=4"
# Get facets
curl http://localhost:3000/products/facets
# Get suggestions
curl "http://localhost:3000/products/suggestions?prefix=wire"
# Get product by ID
curl http://localhost:3000/products/product_1708600000000
# Update product
curl -X PUT http://localhost:3000/products/product_1708600000000 \
-H "Content-Type: application/json" \
-d '{"price": 89.99, "rating": 4.7}'
# Delete product
curl -X DELETE http://localhost:3000/products/product_1708600000000
# Get analytics
curl http://localhost:3000/products/analyticsQueries lebih lambat daripada filters untuk exact matches.
// ❌ Salah - query untuk exact match
{ "match": { "category": "electronics" } }
// ✅ Benar - filter untuk exact match
{ "term": { "category": "electronics" } }Index hanya fields yang Anda perlu untuk search.
// ❌ Salah - index semuanya
"properties": {
"internal_id": { "type": "text" },
"system_timestamp": { "type": "text" }
}
// ✅ Benar - index hanya searchable fields
"properties": {
"internal_id": { "type": "keyword", "index": false },
"system_timestamp": { "type": "date", "index": false }
}Wrong field types hurt performance dan accuracy.
// ❌ Salah - price sebagai text
"price": { "type": "text" }
// ✅ Benar - price sebagai number
"price": { "type": "float" }Large offsets lambat. Gunakan search_after sebagai gantinya.
// ❌ Salah - lambat untuk large offsets
GET /products/_search
{
"from": 100000,
"size": 10
}
// ✅ Benar - gunakan search_after
GET /products/_search
{
"size": 10,
"search_after": ["2026-02-24", "product_id"],
"sort": [{ "created_at": "desc" }, { "_id": "asc" }]
}Elasticsearch operations bisa fail. Implementasikan proper error handling.
// ✅ Proper error handling
try {
const result = await this.elasticsearchService.search({...});
return result;
} catch (error) {
if (error.statusCode === 404) {
throw new NotFoundException('Index not found');
}
throw new InternalServerErrorException('Search failed');
}Monitor index size dan performance.
GET /_cat/indices?v
GET /products/_stats
GET /_cluster/healthPilih analyzers berdasarkan language dan use case.
// ✅ Multi-language support
"name": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
},
"spanish": {
"type": "text",
"analyzer": "spanish"
}
}
}Batch index operations untuk better performance.
// ✅ Bulk indexing
const body = products.flatMap((product) => [
{ index: { _index: 'products', _id: product.id } },
product,
]);
await this.elasticsearchService.bulk({ body });Aliases allow switching indices tanpa downtime.
# Buat new index
PUT /products_v2
# Reindex data
POST /_reindex
{
"source": { "index": "products" },
"dest": { "index": "products_v2" }
}
# Switch alias
POST /_aliases
{
"actions": [
{ "remove": { "index": "products", "alias": "products_alias" } },
{ "add": { "index": "products_v2", "alias": "products_alias" } }
]
}Gunakan query profiling untuk identify slow queries.
GET /products/_search
{
"profile": true,
"query": { "match": { "name": "headphones" } }
}Cache frequently accessed data.
// ✅ Cache facets
@Cacheable('product-facets')
async getFacets() {
return this.elasticsearchService.getProductFacets();
}Terlalu banyak shards hurt performance. Terlalu sedikit limit parallelism.
# Rule of thumb: 1-5 shards per GB dari data
# Untuk 100GB: 20-100 shards
# Untuk 1GB: 1-5 shards
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}Setup monitoring untuk index health dan performance.
# Monitor cluster health
GET /_cluster/health
# Monitor index stats
GET /products/_stats
# Monitor slow queries
GET /_search/stats| Feature | Elasticsearch | Solr | Algolia |
|---|---|---|---|
| Full-Text Search | Excellent | Excellent | Excellent |
| Aggregations | Excellent | Good | Limited |
| Ease of Use | Good | Complex | Very Easy |
| Scalability | Excellent | Good | Managed |
| Cost | Self-hosted | Self-hosted | SaaS |
| Real-Time | Yes | Yes | Yes |
Pilih Elasticsearch ketika:
Pilih Algolia ketika:
Pilih Solr ketika:
Elasticsearch adalah powerful search dan analytics engine yang enable modern applications untuk provide fast, relevant search experiences. Memahami core concepts—indexing, querying, aggregations, dan scoring—mengaktifkan Anda untuk build scalable search systems.
Contoh e-commerce platform mendemonstrasikan production patterns:
Key takeaways:
Mulai dengan simple search use cases. Seiring complexity tumbuh, explore advanced patterns seperti custom analyzers, machine learning, dan cross-cluster search. Fleksibilitas Elasticsearch membuatnya suitable untuk systems dari simple product search hingga complex analytics platforms.
Langkah selanjutnya:
Elasticsearch mentransformasi bagaimana Anda think tentang search—dari simple keyword matching ke intelligent, relevance-ranked results. Master it, dan Anda akan bangun search experiences yang users love.