You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce two new documentation sections to docs-turing/semantic-navigation.md: Custom Sort and Search Rules. Custom Sort covers creating named, multi-level sorts (UI steps, behavior, built-in options, API endpoint /api/sn/{siteId}/custom-sort and related routes) and how the query builder applies sort levels. Search Rules documents rule structure (details, conditions, actions), evaluation semantics (first-match, grouping logic), supported parameters/operators/actions, examples, evaluation pipeline, and REST API endpoints for managing rules. Includes examples and SDK/response formats for integrating sort options and rule-driven behavior in the search UI.
Copy file name to clipboardExpand all lines: docs-turing/semantic-navigation.md
+216Lines changed: 216 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -730,6 +730,222 @@ Spotlights operate in two modes:
730
730
731
731
---
732
732
733
+
<divclassName="page-break" />
734
+
735
+
### Custom Sort
736
+
737
+
Custom Sort allows administrators to define named, multi-level sort options beyond the built-in "relevance", "newest", and "oldest". Each custom sort consists of one or more sort levels (field + direction), applied in priority order to the Solr query.
738
+
739
+
#### Creating a Custom Sort
740
+
741
+
1. Navigate to the SN site's **Custom Sort** tab
742
+
2. Click **New**
743
+
3. Fill in the **Name** (used as the sort identifier in API requests) and optional **Description**
744
+
4. Add one or more **Sort Levels**:
745
+
746
+
| Setting | Description |
747
+
|---|---|
748
+
|**Field**| The Solr field to sort by (selected from the site's configured fields) |
749
+
|**Direction**|`ASC` (ascending) or `DESC` (descending) |
750
+
|**Position**| Priority order — position 0 is the primary sort, position 1 is the first tiebreaker, and so on |
751
+
752
+
Use the move up/down buttons to reorder levels.
753
+
754
+
#### How It Works
755
+
756
+
When a search request includes `sort={customSortName}`, the query builder looks up the custom sort by name and applies each level to the Solr query in position order:
757
+
758
+
```
759
+
# Custom sort "price_then_date" with two levels:
760
+
# Position 0: price ASC
761
+
# Position 1: date DESC
762
+
#
763
+
# Solr query: sort=price asc, date desc
764
+
```
765
+
766
+
#### Built-in Sort Options
767
+
768
+
These are always available alongside any custom sorts:
769
+
770
+
| Value | Behavior |
771
+
|---|---|
772
+
|`relevance`| Default Solr relevance scoring (no explicit sort) |
773
+
|`newest`| Sorts by the site's default date field, descending |
774
+
|`oldest`| Sorts by the site's default date field, ascending |
775
+
776
+
#### Sort Options API
777
+
778
+
The endpoint `GET /api/sn/{siteName}/search/sort-options` returns all available sort options — built-in and custom — as a list of `{value, label}` pairs. This is consumed by the [React SDK's `useTuringSortOptions`](./react-sdk.md#useturingsortoptions) hook to populate sort dropdowns in the search UI.
779
+
780
+
```json
781
+
[
782
+
{ "value": "relevance", "label": "Relevance" },
783
+
{ "value": "newest", "label": "Newest" },
784
+
{ "value": "oldest", "label": "Oldest" },
785
+
{ "value": "price_asc", "label": "Price: Low to High" },
786
+
{ "value": "title_sort", "label": "Title A–Z" }
787
+
]
788
+
```
789
+
790
+
#### REST API
791
+
792
+
| Method | Endpoint | Description |
793
+
|---|---|---|
794
+
|`GET`|`/api/sn/{siteId}/custom-sort`| List all custom sorts |
795
+
|`GET`|`/api/sn/{siteId}/custom-sort/{id}`| Get a custom sort with its levels |
796
+
|`GET`|`/api/sn/{siteId}/custom-sort/fields`| List available fields for sorting |
797
+
|`POST`|`/api/sn/{siteId}/custom-sort`| Create a new custom sort |
798
+
|`PUT`|`/api/sn/{siteId}/custom-sort/{id}`| Update a custom sort |
799
+
|`DELETE`|`/api/sn/{siteId}/custom-sort/{id}`| Delete a custom sort |
800
+
801
+
---
802
+
803
+
<divclassName="page-break" />
804
+
805
+
### Search Rules
806
+
807
+
Search Rules are a powerful automation mechanism that dynamically modifies search behavior based on conditions evaluated at query time. When a rule's conditions match the incoming search request, its actions are applied to the Solr query — overriding sort, adding filters, changing facets, or boosting results — all without any client-side logic.
808
+
809
+
Rules use **first-match semantics**: they are evaluated in position order, and only the first matching rule's actions are applied.
810
+
811
+
#### Rule Structure
812
+
813
+
Each rule has three parts:
814
+
815
+
| Part | Description |
816
+
|---|---|
817
+
|**Details**| Name, description, position (priority), and enabled/disabled toggle |
818
+
|**Conditions**| One or more conditions grouped by parameter — all groups must match (AND between groups) |
819
+
|**Actions**| One or more actions applied when the rule matches |
820
+
821
+
#### Conditions
822
+
823
+
Conditions define **when** a rule triggers. Each condition evaluates a search parameter against a value using an operator.
824
+
825
+
##### Parameters
826
+
827
+
| Parameter | Description | Example |
828
+
|---|---|---|
829
+
|`QUERY`| The user's search query (`q` parameter) | User searched for "education" |
830
+
|`FILTER_QUERY`| Active facet filters (`fq` parameter) | User filtered by `category:books`|
831
+
|`SORT`| Current sort specification | Sort is "newest" |
832
+
|`LOCALE`| Current locale | Locale is `pt_BR`|
833
+
834
+
##### Operators
835
+
836
+
| Operator | Description |
837
+
|---|---|
838
+
|`EQUALS`| Exact match |
839
+
|`CONTAINS`| Value contains the substring |
840
+
|`STARTS_WITH`| Value starts with the substring |
841
+
|`MATCHES_ANY`| Value contains the substring (alias for CONTAINS) |
842
+
|`IS_EMPTY`| Parameter has no value |
843
+
844
+
##### Condition Grouping
845
+
846
+
Conditions are grouped by parameter. Within a group, conditions are combined using the **logic operator** (`AND` or `OR`). Between different parameter groups, `AND` is always used.
847
+
848
+
```
849
+
Example: "When query contains 'laptop' OR 'notebook', AND locale is pt_BR"
850
+
851
+
Condition Group 1 (QUERY, OR):
852
+
- QUERY CONTAINS "laptop"
853
+
- QUERY CONTAINS "notebook"
854
+
855
+
Condition Group 2 (LOCALE):
856
+
- LOCALE EQUALS "pt_BR"
857
+
858
+
Evaluation: (Group 1 OR) AND (Group 2) → both groups must match
859
+
```
860
+
861
+
:::note
862
+
`SORT` and `LOCALE` parameters always use OR logic internally, regardless of the configured logic operator.
863
+
:::
864
+
865
+
#### Actions
866
+
867
+
Actions define **what happens** when the rule matches. Multiple actions can be applied by a single rule.
868
+
869
+
| Action | Description | Value format |
870
+
|---|---|---|
871
+
|`SET_SORT`| Override the sort order | Sort name (e.g., `newest`, custom sort name, or `field:direction`) |
872
+
|`SET_ROWS`| Change the number of results per page | Integer (e.g., `20`) |
873
+
|`ADD_FACETS`| Add facets to the response | Comma-separated field names (e.g., `brand,color`) |
874
+
|`REMOVE_FACETS`| Hide facets from the response | Comma-separated facet names |
A[Search request arrives] --> B[Load enabled rules ordered by position]
888
+
B --> C{Evaluate rule N}
889
+
C -->|All condition groups match| D[Apply rule's actions]
890
+
D --> E[Build Solr query with modified parameters]
891
+
C -->|Not all groups match| F{More rules?}
892
+
F -->|Yes| C
893
+
F -->|No| E
894
+
```
895
+
896
+
Rules are evaluated **before** the Solr query is built, allowing them to modify sort, facets, filters, and boost queries before they are sent to the search engine.
897
+
898
+
#### Examples
899
+
900
+
##### Example 1 — Force sort for product queries
901
+
902
+
When the user searches for "cheap" or "affordable", sort by price ascending:
903
+
904
+
| Part | Configuration |
905
+
|---|---|
906
+
|**Condition**| QUERY CONTAINS "cheap" OR QUERY CONTAINS "affordable" |
907
+
|**Action**| SET_SORT → `price_asc` (a custom sort) |
908
+
909
+
##### Example 2 — Add filters for a specific locale
910
+
911
+
When the locale is `pt_BR`, automatically filter to Portuguese content:
912
+
913
+
| Part | Configuration |
914
+
|---|---|
915
+
|**Condition**| LOCALE EQUALS "pt_BR" |
916
+
|**Action**| ADD_FILTER_QUERY → `language:pt`|
917
+
918
+
##### Example 3 — Boost featured content and limit results
919
+
920
+
When the query is empty (wildcard search), boost featured content and show fewer results:
|`GET`|`/api/sn/{siteId}/search-rule`| List all rules (ordered by position) |
941
+
|`GET`|`/api/sn/{siteId}/search-rule/{id}`| Get a rule with conditions and actions |
942
+
|`GET`|`/api/sn/{siteId}/search-rule/fields`| List available fields for conditions |
943
+
|`POST`|`/api/sn/{siteId}/search-rule`| Create a new rule |
944
+
|`PUT`|`/api/sn/{siteId}/search-rule/{id}`| Update a rule |
945
+
|`DELETE`|`/api/sn/{siteId}/search-rule/{id}`| Delete a rule |
946
+
947
+
---
948
+
733
949
### Top Search Terms
734
950
735
951
Displays reports of the most frequently searched terms for this site. Turing ES records every search query and aggregates statistics across four time windows:
0 commit comments