Blog
ARTIKEL

AMDP – Fuzzy Search im ABAP® mit SAP HANA®

AMDP - Fuzzy Search im ABAP mit SAP HANA

Die SAP HANA Datenbank bietet viele nützliche und coole Funktionen, die über openSQL/ABAP SQL hinaus gehen. Um auf diese Features zuzugreifen und die ganze Power der HANA Datenbank nutzen zu können, gibt es ABAP Managed Database Procedures – AMDP. Damit kann man, ähnlich wie mit EXEC SQL bzw. ADBC (ABAP Database Connectivity), native Datenbank Statements absetzen. In diesem Blogbeitrag beschäftigen wir uns mit den nötigen Anlage- und Implementierungsschritten.

AMDP Klasse und Methode anlegen

AMDP werden als spezielle Methode in einer ABAP Klasse implementiert – die Definition erfolgt wie bei jeder anderen Klasse:

CLASS /cadaxo/cl_ui38_dmo_order_amdp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_amdp_marker_hdb.

    TYPES: ty_orders TYPE STANDARD TABLE OF /CADAXO/UI38D_Demo_Orders WITH DEFAULT KEY.

    METHODS search_orders IMPORTING VALUE(i_search_term) TYPE string
                          EXPORTING VALUE(e_orders)      TYPE ty_orders.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

Durch das Interface IF_AMDP_MARKER_HDB wird die Klasse besonders, was man im Implementierungs-Teil sehen kann:

CLASS /cadaxo/cl_ui38_dmo_order_amdp IMPLEMENTATION.

  METHOD search_orders BY DATABASE PROCEDURE
                       FOR HDB LANGUAGE SQLSCRIPT
                       OPTIONS READ-ONLY
                       USING /cadaxo/ui38d_demo_orders.

    e_orders = select OrderId,
                      CustomerId,
                      ProductId,
                      OrderDate,
                      Quantity,
                      Unit,
                      TotalPrice,
                      Currency,
                      Description,
                      Name,
                      from "/CADAXO/UI38D_DEMO_ORDERS";
  ENDMETHOD.

ENDCLASS.

Die Methodenimplementierung hat einige zusätzliche Statements – Details dazu gibt es auf https://help.sap.com/doc/abapdocu_750_index_htm/7.50/de-de/abapmethod_by_db_proc.htm

BY DATABASE PROCEDURE„Ich bin eine AMDP.“
FOR HDBDerzeit nur „HDB“ – Kommen auch andere Datenbanken?!?!
LANGUAGE SQLSCRIPTWir nehmen SQLSCRIPT.
OPTIONS READ-ONLYWir lesen nur, geändert wird nicht!
USING /cadaxo/ui38d_demo_ordersWir wollen die Bestellungen aus /cadaxo/ui38d_demo_orders.

AMDP Method aufrufen

Aufgerufen wir die AMDP Methode wie jede andere auch:

    new /cadaxo/cl_ui38_dmo_order_amdp( )->search_orders( EXPORTING i_search_term = 'Hat Nägel'
                                                          IMPORTING e_orders      = data(orders) ).

Fuzzy Search

Ok, der SELECT ist nicht gerade spektakulär – das geht auch mit ABAP SQL. Aber eine fehlertolerante Fuzzy Search?!?

Wir wollen Bestellungen zu Kundennamen finden, auch wenn wir den nicht so ganz genau kennen. Dabei hilft uns CONTAINS und FUZZY – https://help.sap.com/docs/SAP_HANA_PLATFORM/691cb949c1034198800afde3e5be6570/9a4da8f6f23b4ebf95c98f1104a56db4.html?&locale=en-US

Wir erweitern den SELECT um eine WHERE Klausel und suchen wie folgt nach dem Namen:

    e_orders = select OrderId,
                      CustomerId,
                      ProductId,
                      OrderDate,
                      Quantity,
                      Unit,
                      TotalPrice,
                      Currency,
                      Description,
                      Name
                      from "/CADAXO/UI38D_DEMO_ORDERS"
                      where contains( Name, :i_search_term, fuzzy( 0.5 ) );

Die FUZZY Funktion liefert alle Namen zurück, deren Vergleich mit dem I_Search_Term mindestens einen Score von 0.5 ergibt. Das klingt erstmal einfach, kann aber ziemlich knifflig werden, vor allem, wenn man die Treffermenge, Genauigkeit und Relevanz für Benutzer optimieren möchte. Der passende Schwellenwert ist dann oft nur empirisch ermittelbar.

SCORE

Um den errechneten Wert der Übereinstimmung anzuzeigen und danach zu sortieren, gibt es die Funktion SCORE. Mit FUZZY( 0.0) werden alle Namen mit einem ermittelten Score größer 0 ausgegeben.

    e_orders = select OrderId,
                      CustomerId,
                      ProductId,
                      OrderDate,
                      Quantity,
                      Unit,
                      TotalPrice,
                      Currency,
                      Description,
                      Name,
                      score( ) as Score
                      from "/CADAXO/UI38D_DEMO_ORDERS"
                      where contains( Name, :i_search_term, fuzzy( 0.0 ) );

Eine Suche nach „Hat Nägel“ ergibt dann z.B. folgende Trefferliste:

Treffliste der Fuzzy Suche mit Score

Komplettes Coding

Das ganze Coding sieht folgendermaßen aus:

CLASS /cadaxo/cl_ui38_dmo_order_amdp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_oo_adt_classrun.

    INTERFACES if_amdp_marker_hdb.

    TYPES: ty_score TYPE p LENGTH 3 DECIMALS 2.
    TYPES: BEGIN OF ty_order.
             INCLUDE TYPE /CADAXO/UI38D_Demo_Orders.
    TYPES:   Score TYPE ty_score,
           END OF ty_order.


    TYPES: ty_orders TYPE STANDARD TABLE OF ty_order WITH DEFAULT KEY.

    METHODS search_orders IMPORTING VALUE(i_search_term) TYPE string
                          EXPORTING VALUE(e_orders)      TYPE ty_orders.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS /cadaxo/cl_ui38_dmo_order_amdp IMPLEMENTATION.

  METHOD search_orders BY DATABASE PROCEDURE
                       FOR HDB LANGUAGE SQLSCRIPT
                       OPTIONS READ-ONLY
                       USING /cadaxo/ui38d_demo_orders.

    e_orders = select OrderId,
                      CustomerId,
                      ProductId,
                      OrderDate,
                      Quantity,
                      Unit,
                      TotalPrice,
                      Currency,
                      Description,
                      Name,
                      score( ) as Score
                      from "/CADAXO/UI38D_DEMO_ORDERS"
                      where contains( Name, :i_search_term, fuzzy( 0.0 ) );
  ENDMETHOD.

  METHOD if_oo_adt_classrun~main.

    new /cadaxo/cl_ui38_dmo_order_amdp( )->search_orders( EXPORTING i_search_term = 'Hat Nägel'
                                                          IMPORTING e_orders      = data(orders) ).

    out->write( name = 'Bestellungen zur Suche:' && '`Hat Nägel`' data = orders ).

  ENDMETHOD.

ENDCLASS.

Passend dazu

Alle Artikel →
Unser Tipp für Sie

Rapid Report Generator for SAP Fiori®

Bestehende ALV-Reports und SAP-Queries in 5 Minuten als Fiori-Bericht bereitstellen – ohne Coding.

Mehr erfahren →