@sinequa/atomic

Query anatomy

The object you send on every search — what each property does, and which one changes the shape of the response.

A query is a plain object. You build it, you pass it, and nothing is hidden: there is no builder to learn and no serialisation step of your own.

Only name is required. It identifies the query web service to run — the server-side configuration that decides which indexes are searched, which facets are computed and which tabs exist. It does not name your query.

the smallest useful query
const query: Query = { name: "<your-query>", text: "quarterly report" };

action decides what comes back

This is the one property that changes the type of the response, and the one that surprises people.

search (default) aggregate open Query action Resultrecords + aggregations + paging AggregateResultaggregations only Resultone tree node expanded
  • search — the default. Documents and facet counts, with pagination.
  • aggregate — pages through one aggregation's items, as a facet's "load more" does. The response carries id, queryName, aggregations and attributes and nothing else: no records, no rowCount, no page. Type it as AggregateResult.
  • open — expands one node of a tree aggregation, listing its children.

Typing an aggregate response as a Result is how twelve absent fields come to look present. See Result anatomy.

Properties

Identity and text

Prop

Type

Narrowing the results

Prop

Type

Paging and ordering

Prop

Type

Aggregations

Prop

Type

Relevance tuning

Raw engine clauses, passed through untouched. Reach for them only with a reason from whoever tuned the index: documentWeight, textPartWeights, relevanceTransforms, spellingCorrectionMode, spellingCorrectionFilter.

spellingCorrectionMode is the one with a visible effect: it decides whether the corrected query is run or merely suggested, which is what result.didYouMean reports.

Recipes

Page through the results

Next and previous page
src/paging.ts
import { createAtomicClient } from "@sinequa/atomic";
import type { Query, Result, ResultPages } from "@sinequa/atomic";

const client = createAtomicClient({
  app: "<your-app>",
  backendUrl: "https://<your-sinequa-server>",
});

await client.initializeConfig();
await client.auth.login();

const base: Query = { name: "<your-query>", text: "quarterly report", pageSize: 10 };

let page = 1;
let result: Result & ResultPages = await client.api.query.search({ ...base, page });

// fetchQuery computes these for you from the response — no arithmetic needed, and
// they are undefined rather than NaN when the response carries no pagination.
while (result.nextPage) {
  page = result.nextPage;
  result = await client.api.query.search({ ...base, page });
  console.log(`page ${result.page}: ${result.records.length} of ${result.rowCount}`);
}

Facets without documents

A home page showing only facet counts, or an advanced-search form populating its value lists:

aggregations only
const result = await client.api.query.search({
  name: "<your-query>",
  isFirstPage: true, // no records come back; aggregations do
});

Load more items of one facet

This is the aggregate action, and the response is not a Result:

paging one aggregation
import type { Aggregation } from "@sinequa/atomic";

// `aggregate` on the client returns the aggregation, refilled with the next slice.
const more: Aggregation = await client.api.query.aggregate(aggregation, {
  name: "<your-query>",
  text: "quarterly report",
});

See Aggregations for skip, count and the $hasMore flag.

Pitfalls

What's next

On this page