Filters
Filters are used by multiple HyperPortal features, they allow to display/get/modify content depending on set conditions.
ALL/ANY condition
With this setting, you can decide whether all conditions should be met or only one.
Example - let`s create two conditions for the list view of the contact entity. The first condition - the country is Belgium. The second condition - gender is female.

If 'ALL' is chosen, only contacts that meet two conditions will be displayed.

If we click on 'meet any of the following conditions' the system will display contacts that meet any of the conditions.


Condition groups
The group of conditions allows us to use multiple conditions as one single condition.
Next to the 'add condition' button, there is an 'add group' button. Instead of one condition, you can add a group of conditions.

Inside the condition group, you can add other conditions or groups.

Group conditions are useful when you want to display/get/modify multiple groups of items. For example, I can create a filter that shows me blue diesel cars and red electric cars. First I need to create two groups.

The first group will contain conditions for blue diesel cars, and the second group will contain conditions for red electric cars. For the main filter, we should select 'meet any conditions', so the cars from each group will appear. We should also select 'meet all' in each group.

The result of this filter will show two groups of cars.

"Is Any Of" and "Is Not Any Of" operators:
We have added new filter options, "Is Any Of" and "Is Not Any Of" with support for bulk pasting.
Rules:
- These filter operators work with the following property types: plain text, Entity, Phone, Email, and Link.
- Item Limit: Supports up to 1,000 items in the filter.
- If you input more than 1000 items in the field, then the remaining items will be copied to the clipboard
- If the filter exceeds 1000 values, the "+ Add condition" button will be disabled

For the Safari browser, the "Copy" button was added, in other browsers the values that exceed 1000 are automatically added to your clipboard after pasting:
- Warning notification popup

- Error notification popup

Use case example:
1. Copy the items from the "country" column in your Excel file.

2. In HyperPortal, click the "Edit View" button.
3. Add a filter for the entity property "Country" (1) and click on the dropdown where you can choose
- "Is Any Of" - the table displayed only items that were added to the filter (2)
- "Is Not Any Of" - the table displays all elements except those added to the filter (2)

4. Paste the copied "Country" values into the "Search Country" field.

5. Click the "Show Result" button to apply the filter.
Dynamic User Filter "⚡️ Me (dynamic)"
The “Me” (dynamic) filter allows dashboards, views, and charts to automatically adapt to the currently logged-in user.
Instead of selecting a fixed user (e.g., Owner = Nicolas), you can configure: "Owner = Me (dynamic)"


At runtime, the system resolves “Me (dynamic)” to the authenticated user viewing the data.
This enables a single dashboard or view configuration to be reused by multiple users while still displaying user-specific data.
Business Impact
Previously, user-specific dashboards required separate configurations such as:
- Owner = Nicolas
- Owner = Ilya
This resulted in:
- Duplicate dashboards
- Poor scalability
With the dynamic user filter, one configuration works for all users.
Scope & Limitations
The “Me” (dynamic) value is available in:
- View filters
- Table filters
- Chart filters
- Dashboard filters
The dynamic option is available only for properties where definitionId = Contact. It can be used exclusively with Contact-based relational fields (e.g., Owner).
Fuzzy search (Similar to)
Fuzzy search is the FUZZY filter operator that finds values spelled with typos, in a different case, without diacritics, or in a different word order. Use it anywhere resilience to human input errors is needed — from ordinary record search to matching "near-duplicates".
This document explains what the FUZZY operator gives you and how exactly it works under the hood — with a focus on how a value is split into words/tokens by the analyzer.
1. In brief
- The FUZZY operator tolerates up to 2 typos per word (edit distance of 2).
- Case and diacritics don't matter: Müller = muller = MULLER, Škoda = skoda.
- Word order doesn't matter: the query jhon doe finds the record Doe, John.
- Every query word must match (AND between words): an extra word narrows the result.
- It is not a substring search: berg does not find iceberg. Matching is against whole tokens (words), not their middle.
- It works on the analyzed (word-split) field, not on the "raw" .keyword value used by the IS / CONTAINS / STARTS_WITH operators.
2. What it does and when to use it
The regular operators compare the value as a whole:
Operator | What it does |
|---|---|
IS | exact match of the whole string (case- and diacritics-insensitive) |
CONTAINS | the value contains a substring |
STARTS_WITH / ENDS_WITH | the value starts/ends with a substring |
FUZZY | each query word matches with up to 2 typos, in any order |
Typical scenarios for FUZZY:
- Search with typos: the user searches for Volkwagen, while the database has Volkswagen.
- Different word order: John Smith and Smith John.
- Different spelling/diacritics: Muller, Müller, Mueller.
- Detecting "near-duplicates" when data is entered by people and minor discrepancies are inevitable.
3. How it works under the hood
Fuzzy search has two sides:
- Indexing — how a value stored in a record is split into tokens in advance.
- Query — how the string typed by the user is turned into a fuzzy condition.
Matching happens between the value's tokens and the query's words. So it is important to understand tokenization first.
3.1. Indexing: splitting a value into tokens (the default analyzer)
All text properties (text, multitext, richtext, file, entity, phoneNumber, email) are indexed in two ways at once:
{
"type": "text",
"analyzer": "default", // ↠analyzed field: the value is split into tokens
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256,
"normalizer": "keyword_normalizer" // ↠raw value as a whole (used by IS/CONTAINS/…)
}
}
}- The propertyId field is analyzed: the value is run through the default analyzer and stored as a set of tokens. This is what FUZZY works on.
- The propertyId.keyword field is the whole value (only folded by case and diacritics via the keyword_normalizer). It is used by IS, CONTAINS, STARTS_WITH, ENDS_WITH, IN.
The default analyzer is a chain of a tokenizer and filters:
flowchart LR
A["source value"] --> B["icu_tokenizer<br/>split into words"]
B --> C["word_split<br/>extra split on hyphens,<br/>case, digits"]
C --> D["icu_normalizer<br/>lowercase,<br/>Unicode normalization"]
D --> E["icu_folding<br/>strip diacritics"]
E --> F["tokens in the index"]"default": {
"type": "custom",
"tokenizer": "icu_tokenizer",
"filter": ["word_split", "icu_normalizer", "icu_folding"]
}What each step does:
- icu_tokenizer — splits text into words by the Unicode text-segmentation rules (UAX #29): on whitespace, punctuation, and boundaries between different writing scripts. Works correctly for most languages.
- word_split (the word_delimiter filter with preserve_original: true) — additionally breaks tokens up while keeping the original variant:
- on intra-word delimiters: Wi-Fi → Wi, Fi;
- on the letter/digit boundary: X5 → X, 5;
- on case change (camelCase): iPhone → i, Phone;
- preserve_original: true — the original token is kept too (iPhone).
- icu_normalizer — lowercases and performs Unicode normalization (a single canonical form of characters).
- icu_folding — strips diacritics and folds characters to their base forms: café → cafe, Müller → muller, Škoda → skoda.
Tokenization examples (illustrative — the exact split is determined by ICU rules):
Field value | Tokens in the index |
|---|---|
Å koda Superb | skoda, superb |
Müller | muller |
iPhone | iphone, i, phone |
e, mail | |
BMW X5 | bmw, x5, x, 5 |
John Doe | john, doe |
Key idea: a value in a record is stored not as one string but as a set of separate word-tokens. Fuzzy search matches the query words against these tokens individually.
3.2. Query: how the fuzzy condition is built
The string entered by the user is turned into a fuzzy condition as follows:
- An empty value (null, undefined, empty string) → FILTER_INVALID error.
- The input is trimmed and split on whitespace (\s+) into words. Repeated and surrounding spaces are collapsed.
- Each word becomes a term field:word~2:
- it targets the analyzed field, not .keyword;
- the ~2 suffix is Lucene fuzzy-search syntax: edit distance 2;
- special characters are escaped before the ~2 suffix is appended.
- If there are several words, they are combined with AND and wrapped in parentheses.
Conversion examples:
User input | Generated condition |
|---|---|
jhon | name:jhon~2 |
jhon doe | (name:jhon~2 AND name:doe~2) |
foo bar baz | (name:foo~2 AND name:bar~2 AND name:baz~2) |
jhon doe | (name:jhon~2 AND name:doe~2) (spaces collapsed) |
jh:on | name:jh\:on~2 (colon escaped) |
Why this gives "word-order independence": each query word is searched among any of the field's tokens independently, and AND requires that all words are found. Order plays no role.
3.3. What "edit distance 2" means
~2 is the maximum Damerau–Levenshtein distance between a query word and a token in the index. Up to 2 operations per word are allowed, where one operation is:
- inserting one character (jon → john),
- deleting one character (johnn → john),
- substituting one character (jahn → john),
- transposing two adjacent characters (jhon → john).
2 is the maximum value that Lucene fuzzy search supports. The query word also passes through the field analyzer before matching, so case and diacritics in the query don't matter either.
4. Examples: what matches and what doesn't
A record with the name property value = John Doe → tokens john, doe.
Query (FUZZY) | Matches? | Why |
|---|---|---|
jhon | ✅ | jhon → john: transposition = 1 operation (≤ 2) |
jon | ✅ | inserting h = 1 operation |
jhon doe | ✅ | both words matched (AND), order doesn't matter |
doe john | ✅ | word order doesn't matter |
john smith | ⌠| smith matched no token → AND fails |
berg (for the value iceberg) | ⌠| not a substring: berg→iceberg = 3 operations |
Diacritics and case: the record Müller (token muller) matches the queries muller, Muller, MÜLLER, mueller (the last one — 1 deletion).
5. Limitations and pitfalls
- No more than 2 typos per word. A heavily distorted word (Volswgn instead of Volkswagen) won't match.
- Short words cause false positives. With distance 2, the word ford matches word, form, fort, food, and so on. For short values (part numbers, 3–4-character codes) fuzzy search is best avoided.
- It is not a substring search. For "contains a fragment" use CONTAINS.
- AND between words. Every extra word in the query narrows the result — all words must match.
- Numbers and punctuation are split by the word_split filter, so behavior on codes, part numbers, and SKUs may be surprising — prefer IS/CONTAINS.
- Empty value is not allowed: an empty string leads to a FILTER_INVALID error.