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: truedefine 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: truedefine 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
| Wert | Bedeutung | Beispiel: Suche “Müller” |
|---|---|---|
| 1.0 | Exakt | Nur “Müller” |
| 0.9 | Fast exakt | ”Müller”, “Mueller” |
| 0.8 | Tolerant (Standard) | “Müller”, “Mueller”, “Muller”, “Müler” |
| 0.7 | Sehr tolerant | Auch “Miller”, “Meller” |
Fuzziness im Code
@Search.searchable: truedefine 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?
| Feldtyp | Empfohlene Fuzziness | Begründung |
|---|---|---|
| IDs, Codes | 1.0 | Exakte Übereinstimmung erforderlich |
| Namen | 0.7 - 0.8 | Tippfehler, Umlaute berücksichtigen |
| Städte, Länder | 0.85 - 0.9 | Leichte Varianten erlauben |
| Beschreibungen | 0.7 - 0.8 | Flexibler für Freitexte |
| E-Mail-Adressen | 1.0 | Exakt |
Ranking: Suchergebnisse priorisieren
Das Ranking bestimmt, welche Treffer zuerst angezeigt werden:
@Search.searchable: truedefine 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
| Stufe | Verwendung |
|---|---|
#HIGH | Primäre Identifikatoren (IDs, Nummern) |
#MEDIUM | Wichtige Geschäftsfelder (Namen, Bezeichnungen) |
#LOW | Sekundä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: truedefine 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: truedefine 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: truedefine 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: #TRANSPARENTdefine 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: trueBookingId,
@Search.defaultSearchElement: trueCustomerName,
@Search.defaultSearchElement: trueDepartureCity,
@Search.defaultSearchElement: trueArrivalCity,
@Search.defaultSearchElement: trueCarrierIdGroß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ägeFür große Datenmengen automatische Suche beim Tippen deaktivieren und explizite Suche erzwingen.
Search Annotations im Überblick
| Annotation | Werte | Beschreibung |
|---|---|---|
@Search.searchable | true/false | Aktiviert Suche auf View-Ebene |
@Search.defaultSearchElement | true/false | Feld ist durchsuchbar |
@Search.fuzzinessThreshold | 0.0 - 1.0 | Ähnlichkeitsschwelle |
@Search.ranking | #HIGH, #MEDIUM, #LOW | Priorität in Ergebnissen |
Kombination mit Filtern
Die generische Suche ergänzt, aber ersetzt nicht die Filter:
@Search.searchable: truedefine 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:
| Aspekt | Empfehlung |
|---|---|
| Aktivierung | @Search.searchable: true auf View |
| Felder | 5-8 relevante Geschäftsfelder |
| Fuzziness | 1.0 für IDs, 0.8 für Namen |
| Ranking | #HIGH für Primärschlüssel |
| Performance | Indizes, begrenzte Feldanzahl |
Mit wenigen Annotationen erreichen Sie eine professionelle Suchfunktion, die Benutzern das schnelle Finden von Daten ermöglicht.
Weiterführende Artikel
- RAP Grundlagen - RESTful ABAP Programming Einführung
- CDS Annotations - Alle Annotationen im Überblick
- RAP Value Helps - Wertehilfen für Filterfelder
- RAP CDS Pattern - Vereinfachte RAP-Architektur