Search

search

The DocuCommit editor (desktop app) and the DocuCommit server (read-only web app) run the same Lucene index over the Markdown files in the repository: same fields, same query syntax, same ranking. The only thing that differs between the two is when the index catches up with a change.

Two ways in

The header search box sits at the top of every page. Type a query and press Enter for the full results page.

Suggestions drop down under the box once you have typed two characters. They come from document titles and tags only — never from body text — and at most eight are offered. Arrow keys move through the list; Enter takes the highlighted one and runs the search.

Autocomplete suggestions in the search box

On the server, a search started from inside a project is scoped to that project (/projects/{project}/search), and one started from inside a library is scoped to that library. The editor has a single global search page.

What is indexed

FieldContents
titleThe document’s title frontmatter
bodyBody prose, with fenced and indented code blocks and raw HTML removed
codeOnly the contents of fenced and indented code blocks
tagsThe document’s tags frontmatter

Prose and code are separated deliberately, so a search for a function name does not have to outrank the paragraphs around it. A query with no field prefix searches all four fields at once.

Query syntax

The box takes classic Lucene syntax. Words are combined with OR unless you say otherwise, so extra words widen the search and improve the score rather than narrowing it.

ExampleWhat it does
backup restoreEither word. Documents with both score higher, and the exact run backup restore is boosted
"merge conflict"The exact phrase — both words, adjacent, in that order
title:dockerMatches in titles only
code:kubectlMatches inside code blocks only
docker NOT composedocker, excluding anything that also mentions compose
deploy*Prefix wildcard — every indexed term that starts with deploy
recieve~Fuzzy — allows a small number of character differences

AND, OR, and NOT must be uppercase. + and - are the shorthand for required and forbidden terms, and parentheses group. A term may not begin with *.

If a query is not valid Lucene syntax at all — a stray bracket, an unclosed quote — it is retried as literal text rather than rejected, so you get results instead of an error message.

Filtering by tag

The results page carries a Tags panel listing the tags that appear in the results, each with the number of documents carrying it. At most 20 tags are shown. Click one to filter the results; click it again to clear. One tag at a time — clicking a second tag replaces the first.

A facet match is exact on the whole tag string, so on-call matches on-call and nothing else. That is different from typing tags:on-call in the box, which goes through the analyser and matches on words.

Search results with highlighted matches and tag facets

Each hit shows a snippet with the matched words wrapped in <mark>. When no snippet can be built around the match, the first 200 characters of the body are shown instead.

How ranking works

A match in the title counts four times as much as one in the body, a match in a tag twice as much; body and code count once each. On top of those weights, a query of two or more words adds a boosted clause for the exact phrase, so a document that contains “merge conflict” as written outranks one that happens to use the two words in different paragraphs. Within all that, Lucene’s own scoring applies — a rare word is worth more than a common one. There is one safety net: a single-word query of at least three characters that returns nothing at all is retried as a fuzzy query across the same four fields, so dokcer still finds the Docker pages. It fires only when the strict search found nothing, and only for one-word queries.

Paging

Results come 20 to a page, with Previous and Next below the list.

When the index catches up

In the editor, saving a document updates that document in the index immediately. Changes that arrive some other way — a Get updates pull, an editor outside DocuCommit, a script — are caught by comparing a signature of your content folder against the one the index last saw, and rebuilding when they differ. That comparison runs at most once every 10 seconds, so an outside change shows up within roughly ten seconds. The interval is docucommit.local.search-signature-ttl (default 10s, environment variable DOCUCOMMIT_LOCAL_SEARCH_TTL).

On the server, the index is rebuilt at startup and again after every sync. Between syncs it does not move, which is the point: what readers search is exactly what has been published.

Limits worth knowing

  • English stemming only. The analyser is Lucene’s English analyser, with English stemming and English stopwords. Text in other languages is indexed and matches whole words, but hus will not find huset.
  • Facet counts are approximate on large result sets. They are counted over the first 500 hits. Below 500 results they are exact; above it, read them as a guide rather than a total.
  • Markdown documents only. The contents of files in _attachments/ are not indexed.
  • The current checkout only. Search covers what is in the working copy now, not Git history. Wording that has been edited away still lives in the repository — git log -S finds it.
  • Comments are not indexed. Server comments are not part of the index and never appear in results.

Tags come from each document’s frontmatter; see Repository layout for the full field table.