The n8n Elasticsearch node lets you index, search, get, and delete documents in an Elasticsearch cluster directly from your n8n workflows. Use it to build search pipelines, log analytics workflows, full-text search features, or anything that needs fast, scalable document querying.
This guide covers everything: configuration, all operations, search query patterns, error handling, and a free workflow JSON you can import right now.
What the Elasticsearch Node Does
The n8n Elasticsearch node connects to any Elasticsearch-compatible cluster (Elasticsearch, OpenSearch, Elastic Cloud, Amazon OpenSearch) and supports these operations:
| Operation | What it does |
|---|---|
| Index | Creates or updates a document by ID |
| Search | Runs a DSL query and returns matching docs |
| Get | Fetches one document by ID |
| Delete | Removes a document by ID |
| Get All | Returns all documents in an index (use carefully) |
Configuration
Before using the node, create an Elasticsearch credential in n8n:
| Field | What to set |
|---|---|
| Host | Your ES host (e.g., http://localhost:9200) |
| Username | Elastic username (leave blank if no auth) |
| Password | Elastic password |
| Ignore SSL Issues | Enable for self-signed certs in dev |
Indexing Documents
The Index operation inserts or replaces a document:
Index: my-index
ID: {{ $json.id }} (optional -- ES generates one if omitted)
Body: {{ $json }}
To upsert (insert or update), set the ID explicitly and enable Upsert in the node settings.
Searching Documents
The Search operation runs an Elasticsearch DSL query.
Match Query (full-text)
{
"query": {
"match": {
"description": "{{ $json.searchTerm }}"
}
}
}
Term Query (exact match)
{
"query": {
"term": {
"status.keyword": "active"
}
}
}
Range Query
{
"query": {
"range": {
"created_at": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
}
Bool Query (multiple conditions)
{
"query": {
"bool": {
"must": [
{ "term": { "status.keyword": "active" } },
{ "match": { "description": "{{ $json.searchTerm }}" } }
],
"filter": [
{ "range": { "created_at": { "gte": "now-7d" } } }
]
}
},
"sort": [ { "created_at": { "order": "desc" } } ],
"size": 25
}
Common Patterns
Ingest Webhook Data into Elasticsearch
Webhook â Code (enrich/validate payload) â Elasticsearch (Index)
Search API Endpoint
Webhook (GET /api/search?q=xxx) â Elasticsearch (Search) â Code (format hits) â Respond to Webhook
Daily Index Maintenance
Schedule Trigger â HTTP Request (DELETE old-index-*) â Elasticsearch (Index log)
Sync Stripe Events to Elasticsearch
Stripe Webhook â Code (map event fields) â Elasticsearch (Index) â Slack (alert on high-value events)
Reading Search Results
The Search operation returns Elasticsearch's raw response. The actual documents are inside hits.hits:
{{ $json.hits.hits[0]._source }} // first document {{ $json.hits.total.value }} // total matches
Use a Code node to flatten multiple hits into an array:
return $input.first().json.hits.hits.map(hit => ({ json: hit._source }));
Gotchas Table
| Symptom | Root cause | Fix |
|---|---|---|
| 404 on index | Index doesn't exist yet | ES auto-creates on first index op -- no manual creation needed unless you want custom mappings |
| 401 Unauthorized | Wrong creds or no password set | Check the credential in n8n settings; for local ES with no auth, leave username/password blank |
| String query not matching | Field is keyword type |
Use term instead of match for exact values, or append .keyword to the field name |
| Search returns only 10 results | ES default size = 10 |
Add "size": 100 (or your limit) to the query body |
| SSL warnings in dev | Self-signed cert | Enable "Ignore SSL Issues" in the credential |
mapping_exception on index |
Field type mismatch | Delete the index and re-index, or use an update by query |
| Performance degrades on large result sets | Fetching too many docs | Use pagination (search_after) or aggregations instead |
Free Workflow JSON â Webhook Search API
This workflow exposes a search endpoint: send GET /api/search?q=your+term, get back formatted results.
{
"name": "Elasticsearch Search API",
"nodes": [
{
"parameters": { "path": "/api/search", "httpMethod": "GET" },
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [250, 300]
},
{
"parameters": {
"operation": "search",
"indexId": "my-index",
"options": {
"query": {
"match": {
"description": "{{ $json.query.q }}"
}
},
"size": 25
}
},
"name": "Search ES",
"type": "n8n-nodes-base.elasticsearch",
"typeVersion": 1,
"position": [480, 300]
},
{
"parameters": {
"jsCode": "var hits = $input.first().json.hits.hits;\nreturn [{ json: { results: hits.map((h) => h._source), total: $input.first().json.hits.total.value } }];"
},
"name": "Format Results",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [710, 300]
},
{
"parameters": { "respondWith": "json", "responseBody": "={{ json.stringify($json) }}" },
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [940, 300]
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Search ES", "type": "main", "index": 0 }]] },
"Search ES": { "main": [[{ "node": "Format Results", "type": "main", "index": 0 }]] },
"Format Results": { "main": [[{ "node": "Respond", "type": "main", "index": 0 }]] }
}
}
Drop a comment with your Elasticsearch use case â I'll share a tailored query pattern (log analytics, e-commerce search, event tracking, etc.).
Workflow Starter Pack ($29)
If you want production-ready workflows with error handling, retry logic, and monitoring already built in, the n8n Workflow Starter Pack includes an Elasticsearch ingest and search workflow alongside 10+ other automation patterns.
Every workflow is documented, tested, and imports in under 2 minutes.
What are you using Elasticsearch for in your n8n workflows? Let me know in the comments.
Top comments (1)
Are you using Elasticsearch with n8n for log analysis, site search, or something else? Drop your use case below — curious what data pipelines people are building with it.