@sinequa/atomic

Sinequa in 5 minutes

The seven backend concepts every example in this documentation relies on, for developers who have never touched Sinequa.

You do not need to administer Sinequa to build an interface on it, but you do need to know what the words mean. Seven concepts cover everything in this documentation. None of them is a client-side idea — they all describe things configured on the server, which is exactly why they keep appearing in your code.

The shape of the system

Sinequa server GET api/v1/app POST api/v1/query records + aggregations Your application Connectors(SharePoint, mail, DBs…) Indexdocuments as typed rows Web applicationyour app name Query web service_query

1. The index

Sinequa crawls your content and stores it as rows with typed columns — much like a database table. A row is a document; columns are title, modified, size, docformat, treepath, authors, plus whatever the administrator mapped from the source (often into generic slots named sourcestr1, sourcecsv2…).

This is why filtering always names a column, and why a display label is not usable as a filter field. See Filtering results.

2. The connectors

What fills the index. Irrelevant to your code, with one consequence worth knowing: which metadata exists is a property of the deployment, not of this library. A field your colleague uses may not exist in your index.

3. The web application — your app

An administrator declares a web application on the server: a named configuration for one front end. Its name is the app value you pass to the client, and every request carries it.

It is not a namespace for your code — it is a set of decisions already made for you: which query web services exist, which facets they expose, which tabs and sort options are offered, which index columns are searchable.

Read it with a single call, and your interface can build itself from it:

Ask the server what it offers
src/discover.ts
import { createAtomicClient } from "@sinequa/atomic";

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

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

const app = await client.api.app.get();

// Query web services available to this application.
console.log("queries:", Object.keys(app.queries));

const query = app.queries[app.defaultQueryName ?? "<your-query>"];

console.log("page size:", query.pageSize);
console.log("facets:", query.aggregations?.map((a) => `${a.name} (${a.column})`));
console.log("sort options:", query.sortingChoices?.map((s) => s.name));
console.log("tabs:", query.tabSearch?.tabs?.map((t) => t.value));

4. The web services — _query and friends

A web service is one configured operation. The library's calls always name the one they use, which is why name: "<your-query>" appears in every search: it identifies the query web service to run, not the query itself.

KindWhat it configuresWhere it appears
querySearch: index selection, facets, tabs, sorting, relevancename of every query
previewThe cached, highlightable rendition of a documentDocument preview
autocompleteSuggestion sources for search-as-you-typeAutocomplete
labelsUser-applied tags, public and privateLabels
datasetNamed, parameterised queries — dashboards, analyticsDatasets
queryexportCSV/XLSX export of a result setExport
sponsoredlinksEditorially promoted links, outside the engine's rankingSponsored links

The default query name is not always `_query`

_query is the conventional name and the one used throughout this documentation, but it is only a default. Read app.defaultQueryName, or list app.queries, rather than assuming it.

5. Aggregations — what a facet really is

An aggregation counts documents per value of a column, computed over the whole result set and returned alongside the results. "PDF (412), Word (87)" in a sidebar is an aggregation on docformat.

Three things follow, and each one has bitten someone:

  • Aggregations come back with the search response, in result.aggregations. You do not request them separately for a normal search.
  • Which aggregations exist is decided by the query web service, not by your code.
  • Some aggregations are distributions: their items are ranges (dates, sizes), and the item's value is an expression rather than a value. Filtering on one needs a dedicated helper — see Filtering results.

6. The principal — who is asking

A principal is the authenticated identity: the user, their groups, and their administrative flags. Security is applied in the index, per document, from the access lists captured at crawl time.

The practical consequence is the one to remember: results are already filtered by the user's rights. Two users running the identical query legitimately get different counts. There is nothing to check client-side, and a document missing from the results may simply be one this user cannot see.

Signing in exchanges credentials for two things: a JWT in an HTTP-only cookie, which JavaScript never sees, and a CSRF token, which the library stores and sends back on every request. Any response may carry a refreshed token, so an active user's session slides forward and does not expire under them.

You rarely deal with this directly — login() covers every mode the server supports — but it explains two observable behaviours: requests need credentials: "include" (the default), and a document preview shown in an <iframe> relies on the cookie rather than on any header your code sets. See How authentication works.

That is the whole vocabulary

On this page