Quickstart: Api frontend integration
The QSC provides a easy configuration of your Search-App with is accessible by an RESTful Api that enable full flexibility in search integration.
Preconditions: In this chapter we assume you have already configured your Search-App
Search Endpoint
The search endpoint supports GET
POST
requests.
The GET
API is for simple integrations and SEO use cases where the url parameter are relevant.
For more complex integrations or SPA we recommend the POST
API.
GET API
The Search Endpoint (Open Api Spec) is requested with the QuasiriS-Query-Language (QSQL) per GET
, POST
and return a search response with contains the found documents and all required informations for the frontend.
GET request parameters
Parameters | Example | Description |
---|---|---|
q | q=foo | Query |
f.id | f.id=42 | Filter the id with default operator AND |
f.id.or | f.id.or=42&f.id.or=44 | Filter the id with operator OR |
f.id.or[] | f.id.or[]=42,44 | Filter the id with operator OR |
f.id.and | f.id.and=42&f.id.and=44 | Filter the id with operator AND |
f.id.and[] | f.id.or[]=42,44 | Filter the id with operator AND |
f.id.not | f.id.not=42&f.id.not=44 | Filter the id that not has the values |
f.id.not[] | f.id.not[]=42,44 | Filter the id that not has the values |
f.price.range | f.id.range | Range filter (Slider) for a configured slider-id |
f.create.daterange | f.crete.daterange=NOW,* | Range filter for date value |
f.create.daterange | f.timestamp.daterange=2021-01-02T23:00:00Z,2021-02-05T20:59:38Z | Range filter for date values |
f.created.humandate | f.created.humandate=last week | Filter for date values |
sort | sort=price | Sort by price |
page | page=3 | Pagination - selected page first page is 1 (default) |
rows | rows=12 | Pagination - Number of returned documents |
ctrl | ctrl=facetDisabled | Control parameter - a comma seperated list of parameters |
ctrl=facetDisabled | ctrl=facetDisabled | disable facets |
ctrl=spellcheckDisabled | ctrl=spellcheckDisabled | disable spellcheck |
result.displayFields | result.displayFields=_score,id | return the fields _score and id in the document result |
result.displayFacets | result.displayFacets=timestamp,created_date | return the facets timestamp and created_date in the result |
Multiple Filter Values
The API provides two ways to use multiple filter values:
- multiple url parameters -
f.id.or=42&f.id.or=44
- array [] syntax with comma seperated values -
f.id.or[]=42,44
Example Request:
Search for wago
with filters available=true
, category=Reihenklemmen
where the documents are sorted by price descending
shown on page 3
.
curl https://qsc-dev.quasiris.de/api/v1/search/ab/products?q=wago&f.available=true&f.categories=Reihenklemmen&sort=pricdesc&page=3
POST API
It is also possible to query the API with a POST
The POST API integration is recommended for more complex queries and Single Page Applications (SPA)
Example Request
This example request contains all possible parameters and filters.
{
"q": "*",
"rows": 10,
"page" : 1,
"requestId": "cdee7a05-8639-4121-a114-7942ba09aa1e9",
"requestOrigin": "my-app",
"trackingTags" : ["foo", "bar"],
"parameters": {
"foo": [
"bar"
]
},
"searchFilters": [
{
"id": "categoryId",
"values": [
"2286"
]
},
{
"id": "publishDate",
"filterDataType": "date",
"filterType": "range",
"minValue": "2024-02-01",
"maxValue": "2001-02-01"
},
{
"id": "price",
"filterType": "range",
"minValue": 0.99,
"maxValue": 11.11
}
],
"sort": {
"sort": "publishDate_asc"
},
"result" : {
}
}
- q - the search query (default: *)
- requestId - the request id used for tracking
- requestOrigin - a identifier where the search is integrated. This parameter is used for tracking
- parameters - a key value map to specifiy custom parameters
- trackingTags - a list of custom tracking tags - for example test requests can be tagged and filtered later in analytics
- result - can define the returned values in more detail. e.g.:
- disable facets
- disable paging
- disable spellcheck
- disable variant
- define a length in a field of a document
Result
Enable / Disable facets - default: true
Enabled
{
"result" : {
"facet" : {
"enabled" : true
}
}
}
Disabled
{
"result" : {
"facet" : {
"enabled" : false
}
}
}
Configure display facets
{
"result" : {
"facet" : {
"facets" : {
"timestamp" : {},
"created_at" : {}
}
}
}
}
- return the timestamp and created_at facet in the response.
- Only configured facets can be displayed, to avoid access to all data of the index
Configure display fields
{
"result" : {
"document" : {
"fields" : {
"_score": {},
"id" : {}
}
}
}
}
Returns the fields _score and id in the response. Only configured fields can be displayed, to avoid access to all data of the index
Paging
- page - the selected page (default: 1)
- rows - the number of rows returned in the result, the default is specified in qsc-console
The QSC has a default limit for paging more than 10,000 documents due to a few important reasons related to performance and system stability:
- Performance Concerns: Retrieving very large volumes of data in a single query can be extremely resource-intensive. As the depth of paging increases (i.e., as you move further and further from the first page), the query becomes slower. This is because the search engine has to count and then skip over a large number of documents to retrieve the data you're asking for, which consumes more memory and CPU.
- Deep Pagination Issues: When QSC performs a search, it essentially ranks all documents that match the search criteria and then provides the top results based on the ranking. To retrieve results beyond the initial set (like the 10,001st document), the search engine must hold onto the interim results of potentially millions of documents. This can cause significant overhead and affect overall search engine health.
- Memory Usage: The deeper you paginate, the more memory is used. This can lead to issues such as increased garbage collection times, slower response times, and even OutOfMemory errors, which might destabilize the cluster.
- Scalability and Stability: By defaulting to limit deep pagination, QSC encourages practices that are scalable and stable.
If you need to retrieve more than 10,000 documents use the nextPageToken
parameter.
This method provide a way to retrieve large datasets without encountering performance degradation or stability issues.
Both the GET
and the POST
API support the nextPageToken
parameter.
For GET
requests use the nextPageToken in the query parameters of the url.
- in the first request set the
nextPageToken=init
- in the result use the
paging.nextPage.token
for the next requestsnextPageToken=FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0
{
"paging": {
"nextPage": {
"token": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0"
},
"pageCount": 2,
"rows": 24
}
}
- call the api until the
result.documents[]
is empty
For `POST requests use the nextPageToken in the request body
{
"q" : "*",
"nextPageToken" : "init"
}
``
#### Filter
As a default the filter is handled as a term filter.
```json
{
"searchFilters": [
{
"id": "categoryId",
"operator" : "AND",
"values": [
"2286"
]
}
]
}
- id - the id of the filter
- values - a array of values
- operator - all values are linked by this operator (default: OR) OR AND NOT
Date Range Filter
{
"searchFilters": [
{
"id": "publishDate",
"filterDataType": "date",
"filterType": "range",
"minValue": "2024-02-01",
"maxValue": "2001-02-01"
}
]
}
- id - the id of the filter
- filterDataType - the data type of the filter
- filterType - specify a range filter
- minValue - the
min
value orfrom
value - maxValue - the
max
value orto
value - for minValue and maxValue the ISO date format is supported
For a date range filter filterDataType: date and filterType:range must be set.
Double Range Filter
{
"searchFilters": [
{
"id": "price",
"filterType": "range",
"minValue": 0.99,
"maxValue": 11.11
}
]
}
Sorting
{
"sort": {
"sort": "publishDate_asc"
}
}
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
},
"statusCode": 200,
"time": 123
}
Every response will return a request time currentTime
, total execution time time
and a http statuscode statusCode
. Some common status codes are listed in the table below
http code | description |
---|---|
200 | OK |
400 | Bad Request (Probably wrong parameters or url structure) |
401 | Unauthorized (Credentials required) |
403 | Forbidden (Not authorized for this user/ role) |
500 | Internal server error |
The other response entities will be described in more detail below.
Request
The response contains request
informations like parameters
, path
, query
, url
required for the frontend search-request-building described below, but its also helpful for debugging purposes.
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
"method": "GET",
"parameters": {
"f.available": [
"true"
],
"f.categories": [
"Reihenklemmen"
],
"page": [
"3"
],
"q": [
"wago"
],
"sort": [
"pricdesc"
]
},
"path": "/api/v1/search/ab/products",
"query": "q=wago&f.available=true&f.categories=Reihenklemmen&sort=pricdesc&page=3",
"url": "http://qsc-dev-admin/api/v1/search/ab/products?q=wago&f.available=true&f.categories=Reihenklemmen&sort=pricdesc&page=3"
},
"result": {
},
"statusCode": 200,
"time": 123
}
Result
The search response contain one or more search result
, where each contains the found documents
with the total
number of hits and additional meta-information required for frontend building or further back-end processing. Each result
has a unique name
, its own statusCode
and execution time
.
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
],
"sliders": [
],
"paging": {
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
Documents
The found documents are returned as list, where each document is a key-value map. The value can be any simple-, list- or any complex data-type.
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
{
"document": {
"categories": [
"Reihenklemmen"
],
"description": "Mini-WSB-Beschriftungskarte als Karte bedruckt 50 ... 99 (2x) nicht dehnbar Aufdruck waagerecht aufrastbar weiß",
"ean": "4017332253505",
"keywords": [
"Reihenklemmen",
"Verteiler & Einbaugeräte",
"Kabelschuhe",
"247524",
"WAGO Kontakttechnik",
"WAGO"
],
"name": "WAGO 247-524 Schnellbezeichnungssystem Mini-WSB weiß",
"previewImageUrl": "https://images.alexander-buerkle.cloud/cdn-cgi/image/width=700,quality=85,format=auto/https://images.deha.de/?file=B36FB7E531AB743AE05332C8A8C00C3D&preset=674x428",
"sku": "0016874",
"supplierProductNumber": "247-524"
},
"fieldCount": 8,
"id": "ec8c6918-2643-4ec9-aa76-d427f3c76052"
}
],
"facets": [
],
"sliders": [
],
"paging": {
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The App specific configuration can be found here under "Searching" tab.
The push or feeding-configuration is out of scope of this topic.
Facets
The facets are auto-generated filters where each facet has a unique id
, filterName
, some meta-information and a list of values which represent a single filter.
A facet can be applied by appending the filterName
to the request url as query-parameter. For this purpose each facet value has a filter
that is already url-encoded and only needs to be append to the request url. The count
show how many documents will be found, when this filter will be applied and the selected
attribute is the boolean indicator for this. Multiple facet values can be selected
- the backend automatically determine which facet values are available/ selectable and return them in the response.
To remove a facet filter the filterName
must be removed from the url query-parameter list.
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
{
"count": 2,
"filterName": "f.available",
"id": "available",
"name": "Verfügbar",
"resultCount": 2121,
"selected": true,
"values": [
{
"count": 1792,
"filter": "f.available=true",
"selected": true,
"value": "true"
},
{
"count": 329,
"filter": "f.available=false",
"value": "false"
}
]
},
{
"count": 2,
"filterName": "f.supplierName",
"id": "supplierName",
"name": "Hersteller",
"resultCount": 1792,
"values": [
{
"count": 1791,
"filter": "f.supplierName=WAGO+Kontakttechnik",
"value": "WAGO Kontakttechnik"
},
{
"count": 1,
"filter": "f.supplierName=PHOENIX++CONTACT",
"value": "PHOENIX CONTACT"
}
]
},
{
"count": 10,
"filterName": "f.categories",
"id": "categories",
"name": "Kategorie",
"resultCount": 2825,
"selected": true,
"values": [
{
"count": 1792,
"filter": "f.categories=Reihenklemmen",
"selected": true,
"value": "Reihenklemmen"
},
{
"count": 313,
"filter": "f.categories=Industrielle+Netzwerktechnik",
"value": "Industrielle Netzwerktechnik"
},
{
"count": 266,
"filter": "f.categories=Kennzeichnungsmaterial",
"value": "Kennzeichnungsmaterial"
},
{
"count": 175,
"filter": "f.categories=Dosen-+%26+Installationsklemmen",
"value": "Dosen- & Installationsklemmen"
},
{
"count": 79,
"filter": "f.categories=Relais+Industrie",
"value": "Relais Industrie"
},
{
"count": 75,
"filter": "f.categories=Netzger%C3%A4te%2C+Trafos+%26+Stromversorgungen",
"value": "Netzgeräte, Trafos & Stromversorgungen"
},
{
"count": 48,
"filter": "f.categories=Stromwandler",
"value": "Stromwandler"
},
{
"count": 47,
"filter": "f.categories=Trennschaltger%C3%A4te%2C+Mess-%2C+%26+Regler-Relais",
"value": "Trennschaltgeräte, Mess-, & Regler-Relais"
},
{
"count": 17,
"filter": "f.categories=Sensor-Aktor+Kabel",
"value": "Sensor-Aktor Kabel"
},
{
"count": 13,
"filter": "f.categories=sonstiges+Werkzeug",
"value": "sonstiges Werkzeug"
}
]
},
{
"count": 0,
"filterName": "f.category",
"id": "category",
"name": "Kategorie",
"resultCount": 0,
"values": []
}
],
"sliders": [
],
"paging": {
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The App specific configuration can be found here under "Facets" tab.
Sliders (Deprecated)
!Deprecated: The sliders are now part of the facets. A slider is a special facet with the type slider. The behavior has been changed to position the sliders in the facet list.
The slider behavior is similar to facets. A slider can be applied by specifying a range, for example searching a document in price range 50 to 129.90 would be f.price=50,129.90
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
],
"sliders": [
{
"count": 405,
"filterName": "f.price",
"id": "price",
"maxRange": 145.0,
"maxValue": 145.0,
"minRange": 15.0,
"minValue": 53.0,
"name": "Preis",
"selected": true
}
],
"paging": {
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The App specific configuration can be found here under "Sliders" tab.
Filters
There are 3 different ways to filter a search result.
- term filter
- range filter for numbers
- daterange filter to filter dates
- humandate filter
Term Filter
The term filter is used to filter string values.
Example
f.type=electronics
Range Filter
The Range filter is used to filter number ranges. The * operator can be used for min and max ranges.
Examples
Filter all products with a price between 12.92 and 99.95
f.price.range=12.95,99.95
Filter all products with a price greater than 12.92
f.price.range=12.95,*
Filter all products with a price less than 99.95
f.price.range=*,99.95
Date Range Filter
The date range filter is used to filter date ranges. The * operator can be used for min and max ranges.
Examples
Filter all news that are published between 23.6.2021 - 23.6.2022
f.publication_date.daterange=2021-06-23T00:00:00Z,2022-06-23T00:00:00Z
Filter all news that are newer than 23.6.21
f.publication_date.daterange=2021-06-23T00:00:00Z,*
Filter all news that are older than 23.6.2022
f.publication_date.daterange=*,2022-06-23T00:00:00Z
Human Date Filter
The human date filter can be used to filter for relative dates.
-
vergangenheit
-
past
-
zukunft
-
future
-
last day
-
yesterday
-
gestern
-
today
-
heute
-
last 3 days
-
letzten 3 tage
-
letzten 7 tage
-
letzten 30 tage
-
this week
-
diese woche
-
last week
-
letzte woche
-
last 3 month
-
letzten 3 monate
-
letzten 6 monate
-
this month
-
dieser monat
-
last month
-
letzter monat
-
last year
-
letztes jahr
-
this year
-
dieses jahr
-
Examples Filter all news that are newer than now
f.publication_date.humandate=future
Pagination
The paging
entity display useful information for the frontend
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
],
"sliders": [
],
"paging": {
"currentPage": 3,
"firstPage": {
"currentPage": false,
"number": 1
},
"lastPage": {
"currentPage": false,
"number": 25
},
"nextPage": {
"currentPage": false,
"number": 4
},
"pageCount": 25,
"previousPage": {
"currentPage": false,
"number": 2
},
"rows": 72
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The App specific configuration can be found here under "Page Config" tab.
Caching
The configuration of a search is cached 5 minutes. This improves performance significantly.
For debugging and testing new configurations it is possible to disable the cache for a specific request.
To disable the cache in the GET
and the POST
the query parameter ctrl=noCache
must be sent in the request.
Sort
The sort
property return all sort options. In the frontend the sort options can be rendered as a dropdown and the user
can change the sorting for the result page.
- id: the id of the sort entry. The id is used in the request to change the sorting
- name: the name of the sort entry. The name can be used to display a text in a drop down in the frontend.
- selected:
- true: this sort options was selected in the request
- false (default): this sort options was not selected in the request
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
],
"sliders": [
],
"paging": {
},
"sort": {
"sort": [
{
"id": "titleAZ",
"name": "Title A-Z"
},
{
"id": "lastUpdate",
"name": "Last Update",
"selected": true
}
]
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The sort options can be configured in the search configuration under "Sorting" tab. It is also possible to change the sort options for each category. TODO link to a detailed description
Redirect
For some queries redirects can be configured. The redirect information can be found in result.products.redirect
Example Response:
{
"currentTime": "2020-02-22T12:34:56+0000",
"request": {
},
"result": {
"products": {
"name": "products",
"documents": [
],
"facets": [
],
"sliders": [
],
"paging": {
},
"redirect": {
"httpCode": 301,
"location": "https://example.com/example-product"
},
"statusCode": 200,
"statusMessage": "OK",
"time": 22,
"total": 1792
}
},
"statusCode": 200,
"time": 123
}
The App specific configuration can be found here.
Search-request-building Guide
On a search page there are typically different kind of actions available like submit query, click on link/ facet, use a slider, paginate or just sort by a field. Each action must be send to the search-engine, so that a new search, adjustment of or navigation through the search results can be performed.
The table below show with information must be provided to the search-engine with a search-request for a specific search-action. However these are best-practices with can differ per use-case/ requirement.
search-action | append params | remove params |
---|---|---|
submit query | none | all |
click filter (facet , navigation , filter , move slider ) | query , filter , sort | page |
perform sort | query , filter | page |
paginate page | query , filter , sort | none |
Search page behaviour
action | documents | filter | pagination | sorting | search box | page |
---|---|---|---|---|---|---|
select filter | reload | keep other filters | reset | - | - | jump to top |
remove filter | reload | keep other filters | reset | - | - | jump to top |
use slider | reload | keep other filters | reset | - | - | jump to top |
change sorting | reload | - | reset | change | - | jump to top |
type in suggest box | - | - | - | - | show suggest | - |
submit a search | reload | reset | reset | - | hide suggest | jump to top |
click on document | - | - | - | - | - | - |
change page | reload | - | change | - | - | jump to top |
change rows | reload | - | reset | - | - | jump to top |
Human Date Filter
The human date filter allow to filter date ranges in a human way.
For example:
- filter all date values in the past for the field myDate
f.myDate.humandate=past
In the followin table all human date filter values are listed.
Value | Description |
---|---|
vergangenheit | |
past | |
zukunft | |
future | |
last day | |
yesterday | |
gestern | |
today | |
heute | |
last 3 days | instead of 3, any number can be used |
letzten 3 tage | |
letzten 7 tage | |
letzten 30 tage | |
this week | |
diese woche | |
last week | |
letzte woche | |
last 3 month | instead of 3, any number can be used |
letzten 3 monate | |
letzten 6 monate | |
this month | |
dieser monat | |
last month | |
letzter monat | |
last year | |
letztes jahr | |
this year | |
dieses jahr |