SharePoint Search finds nothing for a question in an inflected language — add prefix-wildcard stems
SharePoint Search joins bare terms with AND and matches each word against the index as written, so a keyword query copied from a Czech question (inflected forms) often matches zero documents. Expect the same in other heavily inflected languages, and test it. Add a variant built from word stems with a trailing * in code, relax the query before giving up, and never present a "newest documents" listing as the sources of a specific answer.
SharePoint Search spojuje slova přes AND a české tvary neskloňuje, takže dotaz složený ze slov otázky často nenajde nic. Do každé sady dotazů přidej v kódu variantu z kmenů s *, nulu nejdřív zkus uvolnit a výpis „nejnovějších dokumentů“ nikdy nevydávej za zdroje konkrétní odpovědi.
Symptom
A RAG assistant over SharePoint answers "I couldn't find a manual for that". Under the answer it shows a list of sources that have nothing to do with the question (a canteen notice, a benefits page, safety data sheets), and a counter such as "4 266 documents searched". The right document exists, and a person searching by hand finds it.
Cause
Two things compound:
Implicit AND, and exact word forms. Per the KQL reference, free-text expressions without an operator behave as AND, and words are matched as exact terms in the full-text index;
*enables prefix matching. A query such asmanuál SAP založení nákupní objednávky("manual SAP creation purchase order", with every noun in the genitive) requires every term in exactly that form. Measured on a production tenant:Query Hits Top results manuál SAP založení nákupní objednávky1 unrelated same query with a quoted phrase 0 – manu* SAP založ* nákup* objednávk*55 the purchase-order guides that were wanted schvalovací strop("approval ceiling")1 unrelated schvalov* (limit* OR strop* OR pravomoc*)178 the approval-limits directive at position 2 A prefix wildcard (
term*) matches every term that starts with the stem, so it catches the case endings.The zero-hit fallback. A common pattern is: if keyword search returns nothing, list the most recently modified documents in scope (
querytext='*'sorted byWrite). That is useful for "what's new in the library?", but for a specific question it puts random recent documents into the prompt and into the source list, and the "searched" counter then shows the size of the whole scope.
Asking the model that writes the queries to "include synonyms and free-word variants" is not enough: it often returns phrases and full inflected words anyway.
Fix
- Add a stem variant in code to every query set the model generates: lowercase, strip punctuation and
stopwords, cut words longer than about five characters down to a stem and append
*, then join the stems with spaces (AND). Keep the model's own variants as well. The stems are a heuristic; over-matching is fine, because ranking and the answer step filter the results. - Relax before you give up: model queries → stem variant (AND) → stem variant joined with
OR→ only then "nothing found". - Zero hits for a specific question means "nothing found", not "show the latest". Keep the date-sorted listing for genuine corpus questions ("what's new", "what documents do we have about…"). Report a "documents searched" number only for real keyword matches.
- Add domain synonyms where people use a different word than the documents do (ceiling ↔ limit ↔ authority).
A short, maintained list beats hoping the model guesses it. KQL's
WORDS(a, b)matches either term and ranks them as one.
Gotchas
- Wrap each generated query in parentheses before you append scope filters (
Path:"…",IsDocument:1); otherwise a top-levelORin the generated text can leave one of its branches outside the scope. - A wildcard right after a very short stem (
ob*) matches far too much. Keep at least four or five characters before the*, and cut only the case ending, not the derivational part of the word. Measured in a later run on the same tenant, with the same synonym group and no site scope:schval* (strop* OR limit* OR pravomoc*)returned 1 245 hits without the target directive in the top five,schvalov* (strop* OR limit* OR pravomoc*)returned 169 with it at position 2. - KQL supports the wildcard only at the end of a term, never in front of it.
- Evaluate on real user conversations, not on demo content. On demo data, titles tend to match the test questions word for word, and neither failure shows up.
Related
- Microsoft Learn: Keyword Query Language (KQL) syntax reference
- Graph Search returns 0 hits — you passed the user's question as the queryString