Skip to content

Facets all values - #184

Merged
cjmyers merged 3 commits into
masterfrom
facets-all-values
Oct 20, 2026
Merged

cjmyers merged 3 commits into
masterfrom
facets-all-values

Conversation

@cl117

@cl117 cl117 commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

I got Explorer running and finished indexing all the data in Elasticsearch, but a few issues remain:

  • Indexing is slow.
  • The current three-hour limit needs to be extended in the Docker Compose configuration, or Explorer needs to be updated to run indexing in the background.
  • The creator of a private collection cannot be found.
  • The admin setting does not allow Explorer to be turned off. (Can't reproduce)

cl117 added 3 commits October 18, 2026 16:20
The SPARQL facet queries that /facets replaced returned every value;
/facets capped each facet at the requested size (default 50, max 500).
SynBioHub puts dc:creator on the submission collection only, not on its
parts, so a private collection's creator has a count of 1 and never made
the top 50: the owner could not find their own name under Creator.
Locally 1,652 of 5,309 creators occur once.

Raise MAX_FACET_SIZE to 10,000 (five facets x 10,000 stays below
Elasticsearch's search.max_buckets of 65,536); the frontend asks for it.
Warm, locally: 0.65-1.3 s and ~1.1 MB with every value, versus 0.1-0.4 s
for the top 50.
The facet fields were filled by streaming (subject, value) pairs sorted by
subject with keyset paging (FILTER > last + ORDER BY). Virtuoso filtered
and re-sorted the remaining rows for every page, so the cost grew roughly
quadratically: on production (~1M top-level objects) the facet pass took
hours and dominated the rebuild.

query_value_pages() now reads unsorted OFFSET pages (like
query_parts_paged), and index_facet_fields() merges one facet at a time
in memory into {subject: values} before writing one partial update per
part, as before. Memory is one facet at a time (~127 MB peak for 130k
parts locally).

Measured locally, same data and run back to back: old 263 s (Virtuoso
123 s), new 174 s (Virtuoso 43 s); all 132,922 documents end up with
identical facet values. An intermediate variant that appended per page
with a Painless script was correct but slower (373 s) and is not used.
When the index did not exist (e.g. a fresh Elasticsearch volume),
startup() ran the full rebuild at import time, so Flask did not listen
until it finished (an hour or more on production). The container
healthcheck on /info failed after a few minutes and autoheal restarted
Explorer, which started the rebuild over, indefinitely. When a restart
happened after the index had been created, the next start found the
half-built index and skipped the rebuild.

startup() now starts the rebuild in a daemon thread, so /info answers
immediately (searches still return 503 until the index exists). A lock
lets only one full rebuild run at a time: /update returns 409 while one
is running, and the auto-update thread skips its turn, instead of a
second rebuild deleting the index the first is writing.

Checked locally against an empty index: /info answered after 2 s, search
returned 503, and /update during the build returned 409.
@cjmyers
cjmyers merged commit 30418af into master Oct 20, 2026
2 checks passed
@cjmyers
cjmyers deleted the facets-all-values branch October 20, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants