Someone searches a helpdesk for “printer paper,” hoping to find a paper-jam checklist. A list of support notes is useful only if the relevant note can be found. Full-text search, or FTS, builds a lookup structure over words so your application can retrieve matching documents.
This guide uses three fictional notes. You will make their text searchable, compare two query modes, and replace an outdated note. It uses OriginChainDB’s documented HTTP endpoints so the distinction between storing a row and indexing its text is visible.
1. Prepare a small, isolated example
Use a running development instance and a token with the required access. In a Bash-compatible terminal, supply OC_HOST, OC_TENANT and OC_TOKEN through your existing secure environment. OC_HOST is the host name without https://. Do not paste a real token into the article, a shared command file, or a browser application.
Our three document IDs and text are:
| ID | Text |
|---|---|
| n1 | Printer paper jam: open the rear tray. |
| n2 | Printer network setup: check the cable. |
| n3 | Paper supplies: order A4 sheets. |
For this focused exercise, the FTS index uses the label helpdesk_demo.notes and field body. If you also store notes as rows, use the same IDs for the rows and search documents so a hit can be resolved to its source record.
2. Explicitly index the documents
Run this request for the first note:
curl --fail-with-body -X POST \
"https://$OC_HOST/v1/tenants/$OC_TENANT/fts/helpdesk_demo.notes/body" \
-H "Authorization: Bearer $OC_TOKEN" \
-H "Content-Type: application/json" \
-d '{"doc_id":"n1","text":"Printer paper jam: open the rear tray."}'
Repeat with n2 and n3, replacing both the ID and text with the table values. The documented successful indexing response is HTTP 201 with an empty body. An empty response is therefore not, by itself, a failure.
An ordinary SQL or row write does not populate this FTS index. The index and search calls must use exactly the same table and field labels. A spelling change can address a different index and produce an empty result.
3. Compare two different questions
To ask for documents containing both words, choose boolean mode explicitly:
curl --fail-with-body --get \
"https://$OC_HOST/v1/tenants/$OC_TENANT/fts/helpdesk_demo.notes/body" \
-H "Authorization: Bearer $OC_TOKEN" \
--data-urlencode "q=printer paper" \
--data-urlencode "mode=boolean"
With these three notes, n1 is the expected match because it contains both words. This mode returns unranked document IDs. Do not type the word AND into the query as if it were an operator; this endpoint already combines terms according to the selected mode.
For relevance ranking, use the same request with mode=bm25 and add --data-urlencode "k=3". BM25 can consider documents matching either term and returns scored hits. Compare the IDs and read the actual source text. Scores are ranking signals for this corpus and query, not probabilities that an answer is correct.
4. Replace outdated searchable text
Change n1 to “Printer paper jam: open the front tray.” Send the indexing request again with the same doc_id. Re-indexing replaces that document’s previous searchable text. Query for rear and then front; in this isolated corpus, the old term should no longer find n1, while the new term should.
If your application also keeps a source row, update that row and the index through a workflow that records and retries partial failures. Do not assume two separate HTTP calls form one transaction. Keep a repair queue or another recoverable process so an interrupted update can be completed.
5. Judge usefulness with real questions
Try a common misspelling, a phrase from the note, and a question with no good answer. The documented analyzer lowercases and segments words; do not assume that “deliver,” “delivery” and “delivered” automatically match. Add supported search features only after you understand their behavior.
You now have a small keyword-search system with an explicit update path. For search driven by meaning rather than words, evaluate embeddings separately and compare results using the same test questions.
See the FTS reference and indexing guide for response shapes, phrase queries and analysis settings.
Read an inverted index as a small worked example
Imagine writing two lookup lists on paper. The term printer points to n1 and n2; the term paper points to n1 and n3. A boolean query requiring both terms keeps the intersection, n1. It does not need to understand that a paper jam is frustrating. The result follows from the indexed words and the chosen query mode.
That distinction helps explain empty results. A user typing “sheets trapped” may mean the same problem without using either indexed term. The first debugging question is whether the needed words are actually present, not whether the database has forgotten the document. Synonyms, analyzer choices and semantic retrieval can be evaluated later, but each should have its own expected behavior and tests.
Run a small acceptance matrix against the isolated three-note fixture:
| Query | Mode | Expected check |
|---|---|---|
| printer | boolean | IDs n1 and n2 |
| paper | boolean | IDs n1 and n3 |
| printer paper | boolean | Only n1 |
| printer paper | bm25 | Inspect ranked hits and read their source text |
| rear, after replacing n1 | boolean | n1 is absent |
| front, after replacing n1 | boolean | n1 is present |
Do not invent fixed BM25 scores for a tutorial. Their values depend on the corpus, indexed text and scoring configuration. Record the actual returned IDs and scores when you execute the example, while keeping the boolean expectations separate.
Resolve the result before showing a helpdesk answer
An ID such as n1 is a pointer, not the full application record. The search handler should retrieve its source note, check whether the requesting user may read it, confirm that it is current, and return a clear result card. A useful card includes title, passage, revision and a source link. If the row has been deleted while its index entry remains, skip or flag the unresolved hit according to the application’s policy and enqueue repair work.
Avoid presenting a search hit as an automatic instruction to change a device. This example retrieves fictional troubleshooting notes; approval of real operating guidance is a separate organizational process. Likewise, a score should not be styled as “92% correct.” It is a ranking signal for the search calculation, not a calibrated probability of truth.
Diagnose three different kinds of failure
If indexing returns an authorization error, fix the token’s allowed scope through the normal administration process; changing query words will not help. If indexing succeeds but the test returns no IDs, compare tenant, table and field labels byte for byte, then test a single known token. If a hit exists but the UI is empty, inspect source resolution and access decisions separately from retrieval.
Keep your logs useful without storing credentials. Record the non-sensitive document ID, operation category, attempt and error class. A recoverable indexing job should preserve the intended source revision so a later retry cannot silently publish obsolete text. Treat a transient network failure differently from malformed input that requires an editor to correct the record.
The FTS reference also documents response-shape differences between modes. Parse the response for the selected mode rather than assuming every search returns the same object. Before expanding the corpus, keep the six checks above as a regression fixture. They establish the basic contract: the index contains the intended words, replacement removes obsolete searchable text, and every visible hit resolves to allowed evidence.