Generische Suche in RAP: @Search Annotationen für Fiori Elements

Kategorie
RAP
Veröffentlicht
Autor
Johannes

Die generische Suche ermöglicht Benutzern, mit einem einzigen Suchfeld mehrere Felder gleichzeitig zu durchsuchen. In RAP wird diese Funktionalität vollständig deklarativ über @Search Annotationen gesteuert - ohne eine Zeile JavaScript oder UI5-Code.

Das Konzept der generischen Suche

In Fiori Elements Apps erscheint standardmäßig ein Suchfeld oberhalb der Tabelle. Ohne Konfiguration durchsucht es nur explizit definierte Felder. Mit @Search Annotationen bestimmen Sie:

  • Welche Felder durchsucht werden
  • Wie ähnlich Treffer sein müssen (Fuzziness)
  • Wie wichtig ein Treffer ist (Ranking)
┌─────────────────────────────────────────────────┐
│ 🔍 [ München ] 🔎 │ ← Generisches Suchfeld
├─────────────────────────────────────────────────┤
│ Buchungs-ID │ Kunde │ Abflugort │
├───────────────┼────────────────┼───────────────┤
│ 00001234 │ Hans Müller │ München │ ← Treffer
│ 00005678 │ Anna Schmidt │ München │ ← Treffer
│ 00009012 │ München AG │ Frankfurt │ ← Treffer (Kundenname)
└─────────────────────────────────────────────────┘

Grundkonfiguration: @Search.searchable

Die Basisannotation aktiviert die Suche auf View-Ebene:

@Search.searchable: true
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
key BookingId,
CustomerName,
DepartureCity,
ArrivalCity,
FlightDate
}

Wichtig: @Search.searchable: true auf View-Ebene ist Voraussetzung für alle weiteren Such-Annotationen.

Suchbare Felder definieren

Mit @Search.defaultSearchElement: true markieren Sie Felder als durchsuchbar:

@Search.searchable: true
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
@Search.defaultSearchElement: true
key BookingId,
@Search.defaultSearchElement: true
CustomerName,
@Search.defaultSearchElement: true
DepartureCity,
@Search.defaultSearchElement: true
ArrivalCity,
-- Dieses Feld wird NICHT durchsucht
FlightDate,
-- Technische Felder sollten nicht durchsuchbar sein
@UI.hidden: true
CreatedBy
}

In diesem Beispiel findet eine Suche nach “München” Treffer in BookingId, CustomerName, DepartureCity und ArrivalCity - aber nicht in FlightDate oder CreatedBy.

Fuzziness: Ähnlichkeitssuche

Die Fuzziness bestimmt, wie genau der Suchbegriff übereinstimmen muss. Der Wert liegt zwischen 0.0 (beliebige Übereinstimmung) und 1.0 (exakte Übereinstimmung).

Fuzziness-Werte erklärt

WertBedeutungBeispiel: Suche “Müller”
1.0ExaktNur “Müller”
0.9Fast exakt”Müller”, “Mueller”
0.8Tolerant (Standard)“Müller”, “Mueller”, “Muller”, “Müler”
0.7Sehr tolerantAuch “Miller”, “Meller”

Fuzziness im Code

@Search.searchable: true
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
-- Exakte Suche für IDs
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 1.0
key BookingId,
-- Tolerante Suche für Namen (Tippfehler erlaubt)
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.8
CustomerName,
-- Mittlere Toleranz für Städte
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.9
DepartureCity,
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.9
ArrivalCity
}

Wann welche Fuzziness?

FeldtypEmpfohlene FuzzinessBegründung
IDs, Codes1.0Exakte Übereinstimmung erforderlich
Namen0.7 - 0.8Tippfehler, Umlaute berücksichtigen
Städte, Länder0.85 - 0.9Leichte Varianten erlauben
Beschreibungen0.7 - 0.8Flexibler für Freitexte
E-Mail-Adressen1.0Exakt

Ranking: Suchergebnisse priorisieren

Das Ranking bestimmt, welche Treffer zuerst angezeigt werden:

@Search.searchable: true
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
-- Höchste Priorität: Buchungsnummer
@Search.defaultSearchElement: true
@Search.ranking: #HIGH
key BookingId,
-- Mittlere Priorität: Kundenname
@Search.defaultSearchElement: true
@Search.ranking: #MEDIUM
CustomerName,
-- Niedrige Priorität: Städte
@Search.defaultSearchElement: true
@Search.ranking: #LOW
DepartureCity,
@Search.defaultSearchElement: true
@Search.ranking: #LOW
ArrivalCity
}

Ranking-Stufen

StufeVerwendung
#HIGHPrimäre Identifikatoren (IDs, Nummern)
#MEDIUMWichtige Geschäftsfelder (Namen, Bezeichnungen)
#LOWSekundäre Informationen (Beschreibungen, Kommentare)

Sucht der Benutzer nach “00001234”, erscheinen Treffer in BookingId vor Treffern in CustomerName.

Vollständiges Flugbuchungs-Beispiel

Hier ein komplett annotiertes CDS View für die Flugbuchungssuche:

@EndUserText.label: 'Flugbuchung - Projection'
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@Search.searchable: true
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
-- Primärschlüssel mit hohem Ranking
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 1.0
@Search.ranking: #HIGH
@UI.lineItem: [{ position: 10 }]
key BookingId,
-- Flugdaten mit mittlerem Ranking
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.9
@Search.ranking: #MEDIUM
@UI.lineItem: [{ position: 20 }]
CarrierId,
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.9
@Search.ranking: #MEDIUM
@UI.lineItem: [{ position: 30 }]
ConnectionId,
-- Kundendaten mit hoher Fuzziness für Tippfehler
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.8
@Search.ranking: #MEDIUM
@UI.lineItem: [{ position: 40 }]
CustomerName,
-- Ortsangaben durchsuchbar
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.85
@Search.ranking: #LOW
@UI.lineItem: [{ position: 50 }]
DepartureCity,
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.85
@Search.ranking: #LOW
@UI.lineItem: [{ position: 60 }]
ArrivalCity,
-- Datum NICHT durchsuchbar (separate Filter nutzen)
@UI.lineItem: [{ position: 70 }]
@UI.selectionField: [{ position: 10 }]
FlightDate,
-- Status mit Value Help, nicht durchsuchbar
@UI.lineItem: [{ position: 80 }]
@UI.selectionField: [{ position: 20 }]
BookingStatus,
-- Betrag nicht durchsuchbar
@Semantics.amount.currencyCode: 'CurrencyCode'
@UI.lineItem: [{ position: 90 }]
FlightPrice,
@Semantics.currencyCode: true
CurrencyCode,
-- Administrative Felder versteckt und nicht durchsuchbar
@UI.hidden: true
CreatedBy,
@UI.hidden: true
CreatedAt,
@UI.hidden: true
LastChangedBy,
@UI.hidden: true
LastChangedAt
}

Best Practices für durchsuchbare Felder

Felder die durchsuchbar sein sollten

  • Primärschlüssel: BookingId, OrderId, CustomerNumber
  • Namen: CustomerName, ProductName, Description
  • Codes mit Bedeutung: CarrierId, MaterialGroup
  • Ortsangaben: City, Country, Region

Felder die NICHT durchsuchbar sein sollten

  • Datumsfelder: Separate Filterfelder verwenden
  • Numerische Werte: Beträge, Mengen über Filter
  • Technische Felder: GUIDs, Timestamps
  • Administrative Felder: CreatedBy, ChangedAt
  • Binäre Felder: Flags, Status (besser: Value Help Filter)

Beispiel: Gutes vs. schlechtes Design

-- ❌ SCHLECHT: Alles durchsuchbar
@Search.searchable: true
define view entity ZC_Order {
@Search.defaultSearchElement: true
key OrderGuid, -- GUID durchsuchbar?
@Search.defaultSearchElement: true
OrderDate, -- Datum durchsuchbar?
@Search.defaultSearchElement: true
TotalAmount, -- Betrag durchsuchbar?
@Search.defaultSearchElement: true
CreatedAt -- Timestamp durchsuchbar?
}
-- ✅ GUT: Gezielte Auswahl
@Search.searchable: true
define view entity ZC_Order {
@Search.defaultSearchElement: true
@Search.ranking: #HIGH
@Search.fuzzinessThreshold: 1.0
key OrderId, -- Bestellnummer durchsuchbar
@Search.defaultSearchElement: true
@Search.ranking: #MEDIUM
@Search.fuzzinessThreshold: 0.8
CustomerName, -- Kundenname durchsuchbar
@UI.selectionField: [{ position: 10 }]
OrderDate, -- Datum als Filter
@Semantics.amount.currencyCode: 'Currency'
TotalAmount, -- Betrag nicht durchsuchbar
@UI.hidden: true
CreatedAt -- Versteckt
}

Performance-Überlegungen

Indizierung

Durchsuchbare Felder sollten in der Datenbank indiziert sein:

-- In der Tabellendefinition
@AbapCatalog.tableCategory: #TRANSPARENT
define table zflight_book {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
-- Index auf häufig durchsuchte Felder
customer_name : abap.char(80);
departure_city : abap.char(40);
arrival_city : abap.char(40);
}

Anzahl durchsuchbarer Felder begrenzen

-- ❌ Zu viele durchsuchbare Felder (Performance-Problem)
-- 15+ Felder mit @Search.defaultSearchElement: true
-- ✅ Fokussierte Auswahl (5-8 Felder)
@Search.defaultSearchElement: true
BookingId,
@Search.defaultSearchElement: true
CustomerName,
@Search.defaultSearchElement: true
DepartureCity,
@Search.defaultSearchElement: true
ArrivalCity,
@Search.defaultSearchElement: true
CarrierId

Große Datenmengen

Bei großen Datenmengen empfiehlt sich:

@ObjectModel.resultSet.sizeCategory: #XS -- < 100 Einträge
@ObjectModel.resultSet.sizeCategory: #S -- < 1.000 Einträge
@ObjectModel.resultSet.sizeCategory: #M -- < 10.000 Einträge
@ObjectModel.resultSet.sizeCategory: #L -- > 10.000 Einträge

Für große Datenmengen automatische Suche beim Tippen deaktivieren und explizite Suche erzwingen.

Search Annotations im Überblick

AnnotationWerteBeschreibung
@Search.searchabletrue/falseAktiviert Suche auf View-Ebene
@Search.defaultSearchElementtrue/falseFeld ist durchsuchbar
@Search.fuzzinessThreshold0.0 - 1.0Ähnlichkeitsschwelle
@Search.ranking#HIGH, #MEDIUM, #LOWPriorität in Ergebnissen

Kombination mit Filtern

Die generische Suche ergänzt, aber ersetzt nicht die Filter:

@Search.searchable: true
define view entity ZC_FlightBooking
{
-- Durchsuchbar UND als Filter
@Search.defaultSearchElement: true
@Search.ranking: #HIGH
@UI.selectionField: [{ position: 5 }]
key BookingId,
-- Nur durchsuchbar (kein expliziter Filter nötig)
@Search.defaultSearchElement: true
CustomerName,
-- Nur als Filter (nicht durchsuchbar)
@UI.selectionField: [{ position: 10 }]
FlightDate,
-- Nur als Filter mit Value Help
@UI.selectionField: [{ position: 20 }]
@Consumption.valueHelpDefinition: [{
entity: { name: 'ZI_BookingStatusVH' }
}]
BookingStatus
}

Fazit

Die generische Suche in RAP bietet eine leistungsstarke, deklarative Möglichkeit für benutzerfreundliche Suchfunktionen:

AspektEmpfehlung
Aktivierung@Search.searchable: true auf View
Felder5-8 relevante Geschäftsfelder
Fuzziness1.0 für IDs, 0.8 für Namen
Ranking#HIGH für Primärschlüssel
PerformanceIndizes, begrenzte Feldanzahl

Mit wenigen Annotationen erreichen Sie eine professionelle Suchfunktion, die Benutzern das schnelle Finden von Daten ermöglicht.

Weiterführende Artikel