I have a JSON export of Jira issues (or Zendesk tickets). How do I search it like a help-center search?
I have a JSON export of support tickets; how do I search it like a real help-center search? Index the exported JSON on local disk with one xerj autoindex run. In a captured run a description phrase returned 36 hits with per-ticket locators such as tickets:e4, and a status aggregation returned 6 buckets of exactly 30.
Key number: A status terms aggregation returned 6 buckets of exactly 30 tickets each. (as of 2026-08-21 · source: the captured run documented on this page)
TL;DR — XERJ answers a Zendesk ticket search from the exported JSON on local disk, with 1 xerj autoindex run. In a captured run, a phrase from a ticket description returned 36 hits with per-ticket locators such as tickets:e4. A status aggregation returned 6 buckets of exactly 30.
Act as a coding agent. Read https://xerj.org/llms.txt, save a Zendesk incremental ticket export to a local folder as tickets.json, ticket_comments.json and users.json, start a local XERJ node, run `xerj autoindex ./zendesk-export --url http://127.0.0.1:9200 --prefix zd --progress plain`, POST a match_phrase on description, POST a terms aggregation on status with size 0, and report the hit locators, the bucket counts and the difference between the bucket total and track_total_hits.
xerj autoindex ./zendesk-export --url http://127.0.0.1:9200 --prefix zd --progress plain
Index a saved Zendesk export folder from local disk.
curl -s -XPOST http://127.0.0.1:9200/zd-*/_search -H 'content-type: application/json' -d '{"query":{"match_phrase":{"description":"aardvark billing dispute"}},"size":5,"_source":["ax_path","ax_locator","id","subject","status","priority"],"track_total_hits":true}'
Full-text search the ticket description and get a per-ticket locator back.
curl -s -XPOST http://127.0.0.1:9200/zd-json-tickets/_search -H 'content-type: application/json' -d '{"size":0,"aggs":{"by_status":{"terms":{"field":"status","size":20}}},"track_total_hits":true}'
Count tickets per status, exactly, and read the total beside the buckets.
curl -s -XPOST http://127.0.0.1:9200/zd-json-tickets/_search -H 'content-type: application/json' -d '{"query":{"terms":{"tags":["escalated"]}},"size":10,"_source":["id","status","tags"],"track_total_hits":true}'
Filter the multi-valued tags field for one tag value.
Index the saved export
Zendesk's incremental export gives you JSON with a tickets array, a count and an end_of_stream flag. XERJ reads that file as ordinary JSON and gives each exported file its own index.
xerj autoindex ./zendesk-export --url http://127.0.0.1:9200 --prefix zd --progress plain
The captured run read 3 files into 3 datasets and 246 documents live: zd-json-tickets with 181 documents, zd-json-ticket-comments with 61 and zd-json-users with 4. There were 0 junk files.
The fixture generator wrote that payload to Zendesk's incremental-export shape. Zendesk never ran on the host, and no account was connected, so this page tests the exported JSON and not a live integration.
A description phrase finds the exact ticket
A match_phrase on description returned 36 hits. Each hit named the file, the position inside the tickets array, and the ticket's own fields.
| field | example value |
|---|---|
ax_path | tickets.json |
ax_locator | tickets:e4 |
id | 5 |
subject | Aardvark billing dispute on invoice #5 |
status | closed |
priority | normal |
curl -s -XPOST 'http://127.0.0.1:9200/zd-*/_search' \
-H 'content-type: application/json' \
-d '{"query":{"match_phrase":{"description":"aardvark billing dispute"}},"size":5,"_source":["ax_path","ax_locator","id","subject","status","priority"],"track_total_hits":true}'
The locator is what makes this useful to an agent. The value tickets:e4 names element 4 of the tickets array. A follow-up read therefore opens 1 ticket instead of the whole export.
Status counts are exact
A terms aggregation on status returned 6 buckets of exactly 30 documents each. The keys were closed, hold, new, open, pending and solved. XERJ reported doc_count_error_upper_bound 0 and sum_other_doc_count 0, because every aggregation in XERJ is exact.
{"by_status": {"buckets": [{"key": "closed", "doc_count": 30},
{"key": "hold", "doc_count": 30},
{"key": "new", "doc_count": 30},
{"key": "open", "doc_count": 30},
{"key": "pending", "doc_count": 30},
{"key": "solved", "doc_count": 30}],
"doc_count_error_upper_bound": 0, "sum_other_doc_count": 0}}
The buckets total 180 while the same request reported 181 hits. The extra document is the whole-file document for tickets.json, which carries no status. Compare the bucket total with track_total_hits whenever the number is the deliverable.
The fields a ticket produces
XERJ inferred the types from the values, with no mapping written by hand.
| field | inferred type |
|---|---|
description | semantic_text |
subject, raw_subject | text |
status, priority, type, tags, via_channel, custom_fields | keyword |
created_at, updated_at, generated_timestamp | date |
id, requester_id, assignee_id, organization_id, group_id | long |
is_public, has_incidents, allow_channelback | boolean |
The date typing is what makes a range query over created_at work straight after the run. The default embedder in XERJ is lexical feature hashing, so a semantic_text field written by that embedder cannot connect a query to a synonym. Neural embeddings are opt-in through --embed-mode neural.
What this capture does not show
XERJ has no Zendesk connector, no API token flow and no sync job. The node observed 0 distinct non-loopback peers across 185 samples over its whole life. Request the export from Zendesk yourself, save it to disk, then index the folder.
If you flatten the export to JSONL, a line at or above 16 MB is skipped and counted as junk (MAX_LINE, 16 << 20, in engine/crates/xerj-autoindex/src/extract/mod.rs). The rest of the file still indexes.
XERJ runs single-node here, with no replication and no failover. Every number above comes from RUN-B, captured on 2026-08-21. The binary was a ci-test profile build, so no wall-clock figure from this run is published as a performance number.
FAQ
I have a JSON export of support tickets. How do I search it like a real help-center search?
Save the export to disk, index the folder, then send a match_phrase on the description field. The captured run returned 36 hits, each carrying the ticket id, subject, status and priority.
How do I search through an export of Zendesk tickets?
Save the export to local disk and run xerj autoindex on the folder. The captured node observed 0 non-loopback peers over its whole life.
How do I search a Jira export without Jira?
It is the same job: the export is JSON on disk, so the fields are typed and an issue key, a status or a comment token becomes a filter. This capture used a Zendesk export, so the Jira field names were not verified here.
Are the status counts exact or estimated?
Exact. The captured aggregation returned 6 buckets of 30 with doc_count_error_upper_bound 0 and sum_other_doc_count 0.
Why do the status buckets total 180 when the search says 181?
The extra document is the whole-file document for tickets.json, which carries no status. Compare the bucket total with track_total_hits before you report a count.
How do I filter on ticket tags?
XERJ typed tags as a multi-valued keyword, so a terms filter with the tag value returns the matching tickets. custom_fields is keyword too.
Do ticket comments become searchable too?
Yes. The captured run put ticket_comments.json into its own index, zd-json-ticket-comments, with 61 documents.
Evidence
- JSONL line cap is 16 MB (MAX_LINE = 16 << 20). A line at or above that length is skipped; the rest of the file still indexes. —
engine/crates/xerj-autoindex/src/extract/mod.rs
Related
- What's the easiest way to search JSON logs plus some old gzip text logs in the same folder?
- How should an agent figure out what's in a messy data folder before searching?
- Can ChatGPT search a folder on my laptop, or do I need something else?
- I want to point something at a folder and then ask questions about what's in it. What should I use? · same intent: JSONL and data files
- I have a directory of CSV exports. How do I query them without opening each one in Excel? · same intent: JSONL and data files
- How do I index a CSV with many columns? · same intent: JSONL and data files