Skip to main content

Search Functionality 🔍

General

We have quite a few different search abilities throughout the hub. Each search is implemented separately with it's own logic.

The majority of user searches are passed to the backend via the respective API and then are parsed to SQL and added directly to a SQL query.

The majority of search functionality via the Admin dashboard is done via dare filters.

There are however a few cases where a search is passed to the backend via the respective API and then is parsed to SQL and added directly to a SQL query.

See also: 5app Guides - Searching Dashboard

useSearchBar hook

When adding new search functionality to the frontend, e.g. with an ActionBar component, the useSearchBar hook can often be utilised.

It is a hook for syncing queries entered into a search box with the url query parameters.

See also: Storybook - useSearchBar

SQL based searches

When a search is passed to the backend as a search for a direct SQL query, the search fields and search expression need to be defined and formatted in order to be legible for a SQL query.

The util getSearchExpressionFilter can be utilised to create a simple filter for a SQL WHERE case.

Usage example:

import getSearchExpressionFilter from '../../utils/getSearchExpressionFilter.js';

export async function getExampleAudit(req, res) {
const {domainId} = req.user;
const {format, search, userId} = req.query;

const searchFields = [
'targetUser.name',
'targetUser.first_name',
'targetUser.last_name',
];

const searchExpressionFilter = getSearchExpressionFilter({
search,
searchFields,
});

const query = SQL`
SELECT
targetUser.id AS userId,
FROM changelog
JOIN users targetUser ON (targetUser.id = changelog.ref_id)
WHERE
changelog.ref_type = 'user'
AND changelog.domain_id = ${domainId}
${searchExpressionFilter}
`;

const queryResult = await db.queryReadOnly(query)

res.send({
items: queryResult,
});
}

Dare bases searches and the parseSearch util

The parseSearch util is used in the frontend to format a received search value (input by the user) into a dare legible format.

The output of the util is then passed on to the dare query as a query filter. The filter can either be added directly to the dare query, if the query is located on the frontend. Otherwise the filter can be passed to the backend via the api and utilised accordingly there.

The parseSearch util is utilised for a lot of search functionality in the Admin dashboard.

Usage example:

import parseSearch from 'utils/parseSearch';

export function parseNewSearch(search?: string) {
let filter = {}

parseSearch(search, {

text(values) {
const name = `%${values.join('%')}%`;
filter.name = value;
},
created([value]) {
filter.created_time = value;
},
updated([value]) {
filter.updated_time = value;
},
id(values) {
filter.id = values;
},
});

return filter // will filter a table for either `name`,`created_time` or `updated_time` or `id`
}

Dashboard Dare Search Syntax

SyntaxExampleFilter Description
valueAndrewWords without protocol (:) are treated as search terms.
is:propis:adminmatches prop = true
not:propnot:adminmatches prop = false
has:prophas:teamMatches a non-empty SET prop
no:propno:teamMatches an empty SET prop
prop:value or prop:"value"team:MyTeammatches prop = value.
prop:..valuecreated:..2016-01-01matches prop with values less than value.
prop:value..created:2016-01-01..matches prop with values greater than value.
prop:value1..value2rank:1..100matches prop with values between two values
sort:prop-(asc OR desc)sort:updated-descSorts the results by property (asc or desc)

Available Search Definitions (incomplete)

Search Common

Search definitions available to all search inputs

TypeDescription
AndrewFilter items by name "Andrew"
is:deletedMatch deleted items
not:deleted(Default) Match only non-deleted items
created:2016-01-01Matches created on "2016-01-01"
created:2016-01-01..Matches created since "2016-01-01"
created:..2016-01-01Matches created before "2016-01-01"
created:2015-01-01..2016-01-01Matches created between "2015-01-01" and "2016-01-01"
updated:2016-01-01Matches updated on "2016-01-01"
updated:2016-01-01..Matches updated since "2016-01-01"
updated:..2016-01-01Matches updated before "2016-01-01"
updated:2015-01-01..2016-01-01Matches updated between "2015-01-01" and "2016-01-01"
sort:updated-descSorts the results by most recently updated first.
sort:updated-ascSorts the results by most recently updated last.
sort:created-descSorts the results by most recently created first.
sort:created-ascSorts the results by most recently created last.

Search Assets

TypeDescription
My fileSearch assets with titles
type:fileMatch assets of type file
type:folderMatch assets of type folder
owner:commonChanges the bucket of assets, used to include assets in collections, and includes those shared via a parent hub
refid:MY_REF_123Search for asset containing the customer refid
is:ratedHas been rated by a user
opened:2016-01-01Opened in date range
folder:rootMatch assets in the root folder only
folder:123Filter assets in a folder, by id 123
folder:123,456Filter assets in a folder with id 123 or 456

Search Nudges

TypeDescription
My nudgeMatches nudges with name containing My nudge
logInAgainMatches nudges with goal Log in again
logInFirstTimeMatches nudges with goal Log in for the first time
openContentMatches nudges with goal Open content
completeContentMatches nudges with goal Complete content
id:1Matches nudges with id 1
id:1,2Matches nudges with id 1 and id 2
created:2016-01-01Matches created on "2016-01-01"
updated:2016-01-01..Matches updated since "2016-01-01"

Search Playlists

TypeDescription
My playlistMatches title with My playlist
no:topicMatches playlists which are not associated with a topic
has:topicMatches playlists which belong on one or more topics
topic:"My Topic"Matches playlists which belong to the topic "My Topic"
has:badgeMatches playlists which have a badge assigned to them

Search Users

TypeDescription
AndrewMatches users with andrew
is:adminFilter only admin
not:adminFilter out admin
is:invitedFilter users who have been sent an email invite
not:invitedFilter users who have not been sent an email invite
is:inactiveFilter users who have never logged in
not:inactiveFilter users who used who have used the system atleast once
no:teamFilter users who dont belong to any teams
session:2017-11..2018-01Filter users who have had a session in the date range
openedasset:123Filter users who have opened an Asset using Asset ID
activity:123Last active inrange activity:2018-01
team:MyTeamFilter users in team "MyTeam"
team:A-Team,B-TeamFilter users in either "A-Team" or "B-Team"
sort:active-descSorts users by most recent active first.
sort:active-ascSorts users by most recent active last.

Further resources