DEV Community

Pirate Prentice
Pirate Prentice

Posted on

n8n Elasticsearch Node: Index, Search, and Query Documents (Free Workflow JSON)

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 }}
Enter fullscreen mode Exit fullscreen mode

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 }}"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Term Query (exact match)

{
  "query": {
    "term": {
      "status.keyword": "active"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Range Query

{
  "query": {
    "range": {
      "created_at": {
        "gte": "now-1d/d",
        "lt": "now/d"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

Common Patterns

Ingest Webhook Data into Elasticsearch

Webhook — Code (enrich/validate payload) — Elasticsearch (Index)
Enter fullscreen mode Exit fullscreen mode

Search API Endpoint

Webhook (GET /api/search?q=xxx) — Elasticsearch (Search)  — Code (format hits)  — Respond to Webhook
Enter fullscreen mode Exit fullscreen mode

Daily Index Maintenance

Schedule Trigger — HTTP Request (DELETE old-index-*)  — Elasticsearch (Index log)
Enter fullscreen mode Exit fullscreen mode

Sync Stripe Events to Elasticsearch

Stripe Webhook — Code (map event fields) — Elasticsearch (Index)  — Slack (alert on high-value events)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Use a Code node to flatten multiple hits into an array:

return $input.first().json.hits.hits.map(hit => ({ json: hit._source }));
Enter fullscreen mode Exit fullscreen mode

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 }]] }
  }
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
pirateprentice profile image
Pirate Prentice

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.