Export
Handing the user a CSV, XLSX or JSON of a result set — and dealing with the raw Response the call returns.
client.api.query.export() asks the server to render a result set as a file. Unlike every other call in this
library, it hands back the raw Response rather than parsed data — the body is a file, so it is yours to turn
into a download.
Exporting the current results
Export, then hand the file to the browser
import { createAtomicClient } from "@sinequa/atomic";
import type { ExportQueryModel, Query } from "@sinequa/atomic";
const client = createAtomicClient({
app: "<your-app>",
backendUrl: "https://<your-sinequa-server>",
});
await client.initializeConfig();
await client.auth.login();
// The export web service is named in the configuration, like every other one.
const app = await client.api.app.get();
export async function exportResults(query: Query) {
const model: ExportQueryModel = {
format: "Xlsx",
export: "Result", // the whole result set, not just the current page
webservice: app.queryExport,
maxcount: 5000,
queryName: query.name,
filename: "search-results",
// Omit to let the server decide which columns to include.
exportedColumns: ["title", "modified", "docformat", "authors"],
};
// This call returns the raw Response: the body is a file, not JSON.
const response = await client.api.query.export({
model,
appName: app.name ?? "<your-app>",
query,
});
await download(response, `${model.filename}.xlsx`);
}
async function download(response: Response, fallbackName: string) {
const blob = await response.blob();
// Prefer the name the server sent, if it sent one.
const disposition = response.headers.get("content-disposition") ?? "";
const name = /filename="?([^"]+)"?/.exec(disposition)?.[1] ?? fallbackName;
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = name;
anchor.click();
// Release the blob, or it is held for the lifetime of the document.
URL.revokeObjectURL(url);
}import { Injectable, inject, signal } from "@angular/core";
import type { CCApp, ExportQueryModel, Query } from "@sinequa/atomic";
import { SINEQUA } from "./sinequa";
@Injectable({ providedIn: "root" })
export class ExportService {
private readonly client = inject(SINEQUA);
readonly busy = signal(false);
/**
* Exports a result set and triggers the browser download. The call returns a raw
* Response — the body is a file, so nothing is parsed for us.
*/
async export(app: CCApp, query: Query, format: ExportQueryModel["format"] = "Xlsx") {
this.busy.set(true);
try {
const model: ExportQueryModel = {
format,
export: "Result",
webservice: app.queryExport,
maxcount: 5000,
queryName: query.name,
filename: "search-results",
};
const response = await this.client.api.query.export({
model,
appName: app.name ?? "",
query,
});
await this.download(response, `${model.filename}.${format.toLowerCase()}`);
} finally {
this.busy.set(false);
}
}
private async download(response: Response, fallbackName: string) {
const blob = await response.blob();
const disposition = response.headers.get("content-disposition") ?? "";
const name = /filename="?([^"]+)"?/.exec(disposition)?.[1] ?? fallbackName;
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = name;
anchor.click();
// Release the blob, or it is held for the lifetime of the document.
URL.revokeObjectURL(url);
}
}import type { CCApp, ExportQueryModel, Query } from "@sinequa/atomic";
import { useCallback, useState } from "react";
import { ready, sinequa } from "./sinequa";
async function download(response: Response, fallbackName: string) {
const blob = await response.blob();
const disposition = response.headers.get("content-disposition") ?? "";
const name = /filename="?([^"]+)"?/.exec(disposition)?.[1] ?? fallbackName;
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = name;
anchor.click();
// Release the blob, or it is held for the lifetime of the document.
URL.revokeObjectURL(url);
}
export function useExport(app: CCApp | undefined) {
const [busy, setBusy] = useState(false);
const run = useCallback(
async (query: Query, format: ExportQueryModel["format"] = "Xlsx") => {
if (!app) return;
setBusy(true);
try {
const model: ExportQueryModel = {
format,
export: "Result",
webservice: app.queryExport,
maxcount: 5000,
queryName: query.name,
filename: "search-results",
};
await ready;
// Returns a raw Response: the body is a file, not JSON.
const response = await sinequa.api.query.export({
model,
appName: app.name ?? "",
query,
});
await download(response, `${model.filename}.${format.toLowerCase()}`);
} finally {
setBusy(false);
}
},
[app],
);
return { run, busy };
}The model
Prop
Type
Exporting a selection means the documents the user picked, so your interface has to have tracked them —
$selected on each record is there for that, and it is yours to maintain.