|
| 1 | +--- |
| 2 | +outline: [2, 4] |
| 3 | +--- |
| 4 | +# Fuzzy Search |
| 5 | + |
| 6 | +On SAP HANA you can match strings tolerantly — typos, missing letters, transposed characters — with the `CONTAINS` SQL function in fuzzy mode. The score is a value between `0.0` (no match) and `1.0` (exact match); pass a threshold to `FUZZY( )` and HANA filters out rows below it. |
| 7 | + |
| 8 | +Wire it to a UI5 `search_field` in the table toolbar and you get an ALV-style search that forgives the user's typing. |
| 9 | + |
| 10 | +#### Minimal Example |
| 11 | + |
| 12 | +```abap |
| 13 | +CLASS z2ui5_cl_sample_fuzzy DEFINITION PUBLIC. |
| 14 | +
|
| 15 | + PUBLIC SECTION. |
| 16 | + INTERFACES z2ui5_if_app. |
| 17 | + TYPES: |
| 18 | + BEGIN OF ty_customer, |
| 19 | + kunnr TYPE kna1-kunnr, |
| 20 | + name1 TYPE kna1-name1, |
| 21 | + ort01 TYPE kna1-ort01, |
| 22 | + END OF ty_customer. |
| 23 | + DATA mt_customers TYPE STANDARD TABLE OF ty_customer WITH EMPTY KEY. |
| 24 | + DATA mv_search TYPE string. |
| 25 | +
|
| 26 | +ENDCLASS. |
| 27 | +
|
| 28 | +CLASS z2ui5_cl_sample_fuzzy IMPLEMENTATION. |
| 29 | + METHOD z2ui5_if_app~main. |
| 30 | +
|
| 31 | + CASE abap_true. |
| 32 | +
|
| 33 | + WHEN client->check_on_init( ). |
| 34 | + load_data( ). |
| 35 | + render( ). |
| 36 | +
|
| 37 | + WHEN client->check_on_event( `SEARCH` ). |
| 38 | + load_data( ). |
| 39 | + client->view_model_update( ). |
| 40 | +
|
| 41 | + ENDCASE. |
| 42 | +
|
| 43 | + ENDMETHOD. |
| 44 | +
|
| 45 | + METHOD load_data. |
| 46 | +
|
| 47 | + "CONTAINS(<col>, <pattern>, FUZZY(<threshold>)) — only available on HANA. |
| 48 | + "Threshold 0.8 ≈ tolerates one or two typos in a short word. |
| 49 | + SELECT FROM kna1 |
| 50 | + FIELDS kunnr, name1, ort01 |
| 51 | + WHERE @mv_search = '' |
| 52 | + OR contains( ( name1, ort01 ), @mv_search, 'FUZZY(0.8)' ) = 1 |
| 53 | + INTO TABLE @mt_customers |
| 54 | + UP TO 100 ROWS. |
| 55 | +
|
| 56 | + ENDMETHOD. |
| 57 | +
|
| 58 | + METHOD render. |
| 59 | +
|
| 60 | + DATA(view) = z2ui5_cl_xml_view=>factory( )->shell( )->page( `Customers` ). |
| 61 | + DATA(tab) = view->table( client->_bind( mt_customers ) growing = abap_true ). |
| 62 | +
|
| 63 | + tab->header_toolbar( )->overflow_toolbar( |
| 64 | + )->title( `Customers` |
| 65 | + )->toolbar_spacer( ) |
| 66 | + )->search_field( |
| 67 | + value = client->_bind_edit( mv_search ) |
| 68 | + width = `20rem` |
| 69 | + placeholder = `try a misspelled name…` |
| 70 | + search = client->_event( `SEARCH` ) ). |
| 71 | +
|
| 72 | + tab->columns( )->column( )->text( `Customer` )->get_parent( |
| 73 | + )->column( )->text( `Name` )->get_parent( |
| 74 | + )->column( )->text( `City` ). |
| 75 | + tab->items( )->column_list_item( )->cells( |
| 76 | + )->text( `{KUNNR}` )->text( `{NAME1}` )->text( `{ORT01}` ). |
| 77 | +
|
| 78 | + client->view_display( view->stringify( ) ). |
| 79 | +
|
| 80 | + ENDMETHOD. |
| 81 | +
|
| 82 | +ENDCLASS. |
| 83 | +``` |
| 84 | + |
| 85 | +Typing `Muller` matches `Müller`, `Hambrug` matches `Hamburg` — the lower the threshold, the more lenient (and the noisier) the result. |
| 86 | + |
| 87 | +#### Tuning the Threshold |
| 88 | + |
| 89 | +| Threshold | Behaviour | |
| 90 | +| --------- | ------------------------------------------------------ | |
| 91 | +| `1.0` | Exact match only — same as `LIKE` without wildcards | |
| 92 | +| `0.9` | Very strict — only tiny variations | |
| 93 | +| `0.8` | Default sweet spot — tolerates one or two typos | |
| 94 | +| `0.7` | Lenient — short words start matching unrelated rows | |
| 95 | +| `< 0.7` | Mostly noise on real data | |
| 96 | + |
| 97 | +#### Multiple Columns |
| 98 | + |
| 99 | +Pass a list of columns to search several fields at once — HANA returns the best score across them: |
| 100 | + |
| 101 | +```abap |
| 102 | +WHERE contains( ( name1, ort01, stras ), @mv_search, 'FUZZY(0.8)' ) = 1 |
| 103 | +``` |
| 104 | + |
| 105 | +#### Returning the Score |
| 106 | + |
| 107 | +To order rows by relevance, expose the fuzzy score with `SCORE( )` and sort on it: |
| 108 | + |
| 109 | +```abap |
| 110 | +SELECT FROM kna1 |
| 111 | + FIELDS kunnr, name1, ort01, |
| 112 | + score( ) AS rank |
| 113 | + WHERE contains( ( name1, ort01 ), @mv_search, 'FUZZY(0.8)' ) = 1 |
| 114 | + ORDER BY rank DESCENDING |
| 115 | + INTO TABLE @mt_customers |
| 116 | + UP TO 100 ROWS. |
| 117 | +``` |
| 118 | + |
| 119 | +::: warning |
| 120 | +`CONTAINS … FUZZY( )` is HANA-only. On non-HANA databases the statement raises an SQL error — guard it behind a release check or fall back to `LIKE` if your code may run elsewhere. |
| 121 | +::: |
| 122 | + |
| 123 | +::: tip |
| 124 | +For the full set of options — `textsearch`, `similarcalculationmode`, `spellcheck` — see the [SAP HANA fuzzy search guide](https://help.sap.com/docs/SAP_HANA_PLATFORM/691cb949c1034198800afde3e5be6570/ee08fb15621c4cb98ce8acaef8b3a48d.html). |
| 125 | +::: |
0 commit comments