La recherche générique permet aux utilisateurs de rechercher simultanément dans plusieurs champs avec un seul champ de recherche. Dans RAP, cette fonctionnalité est entièrement contrôlée de manière déclarative via les annotations @Search - sans une seule ligne de JavaScript ou de code UI5.
Le concept de la recherche générique
Dans les applications Fiori Elements, un champ de recherche apparaît par défaut au-dessus du tableau. Sans configuration, il ne recherche que dans les champs explicitement définis. Avec les annotations @Search, vous déterminez :
- Quels champs sont recherchés
- À quel point les résultats doivent être similaires (Fuzziness)
- L’importance d’un résultat (Ranking)
┌─────────────────────────────────────────────────┐│ 🔍 [ München ] 🔎 │ ← Champ de recherche générique├─────────────────────────────────────────────────┤│ Buchungs-ID │ Kunde │ Abflugort │├───────────────┼────────────────┼───────────────┤│ 00001234 │ Hans Müller │ München │ ← Résultat│ 00005678 │ Anna Schmidt │ München │ ← Résultat│ 00009012 │ München AG │ Frankfurt │ ← Résultat (nom du client)└─────────────────────────────────────────────────┘Configuration de base : @Search.searchable
L’annotation de base active la recherche au niveau de la vue :
@Search.searchable: truedefine view entity ZC_FlightBooking as projection on ZI_FlightBooking{ key BookingId, CustomerName, DepartureCity, ArrivalCity, FlightDate}Important : @Search.searchable: true au niveau de la vue est un prérequis pour toutes les autres annotations de recherche.
Définir les champs interrogeables
Avec @Search.defaultSearchElement: true, vous marquez les champs comme interrogeables :
@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}Dans cet exemple, une recherche de “München” trouve des résultats dans BookingId, CustomerName, DepartureCity et ArrivalCity - mais pas dans FlightDate ou CreatedBy.
Fuzziness : Recherche de similarité
La Fuzziness détermine à quel point le terme de recherche doit correspondre exactement. La valeur est comprise entre 0.0 (correspondance arbitraire) et 1.0 (correspondance exacte).
Valeurs de Fuzziness expliquées
| Valeur | Signification | Exemple : Recherche “Müller” |
|---|---|---|
| 1.0 | Exact | Uniquement “Müller” |
| 0.9 | Presque exact | ”Müller”, “Mueller” |
| 0.8 | Tolérant (Standard) | “Müller”, “Mueller”, “Muller”, “Müler” |
| 0.7 | Très tolérant | Aussi “Miller”, “Meller” |
Fuzziness dans le 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}Quelle Fuzziness pour quel type de champ ?
| Type de champ | Fuzziness recommandée | Justification |
|---|---|---|
| IDs, Codes | 1.0 | Correspondance exacte requise |
| Noms | 0.7 - 0.8 | Tenir compte des fautes de frappe, umlauts |
| Villes, Pays | 0.85 - 0.9 | Permettre des variantes légères |
| Descriptions | 0.7 - 0.8 | Plus flexible pour le texte libre |
| Adresses e-mail | 1.0 | Exact |
Ranking : Prioriser les résultats de recherche
Le Ranking détermine quels résultats sont affichés en premier :
@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}Niveaux de Ranking
| Niveau | Utilisation |
|---|---|
#HIGH | Identifiants primaires (IDs, numéros) |
#MEDIUM | Champs métier importants (noms, désignations) |
#LOW | Informations secondaires (descriptions, commentaires) |
Si l’utilisateur recherche “00001234”, les résultats dans BookingId apparaîtront avant les résultats dans CustomerName.
Exemple complet de réservation de vol
Voici une vue CDS entièrement annotée pour la recherche de réservation de vol :
@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}Bonnes pratiques pour les champs interrogeables
Champs qui doivent être interrogeables
- Clés primaires : BookingId, OrderId, CustomerNumber
- Noms : CustomerName, ProductName, Description
- Codes avec signification : CarrierId, MaterialGroup
- Indications de lieu : City, Country, Region
Champs qui NE DOIVENT PAS être interrogeables
- Champs de date : Utiliser des champs de filtre séparés
- Valeurs numériques : Montants, quantités via filtres
- Champs techniques : GUIDs, Timestamps
- Champs administratifs : CreatedBy, ChangedAt
- Champs binaires : Flags, Status (mieux : filtres Value Help)
Exemple : Bon vs. mauvais 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}Considérations de performance
Indexation
Les champs interrogeables doivent être indexés dans la base de données :
-- 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);}Limiter le nombre de champs interrogeables
-- ❌ 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: trueCarrierIdGrands volumes de données
Pour de grands volumes de données, il est recommandé de :
@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ägePour de grands volumes de données, désactivez la recherche automatique lors de la saisie et forcez la recherche explicite.
Aperçu des annotations Search
| Annotation | Valeurs | Description |
|---|---|---|
@Search.searchable | true/false | Active la recherche au niveau de la vue |
@Search.defaultSearchElement | true/false | Le champ est interrogeable |
@Search.fuzzinessThreshold | 0.0 - 1.0 | Seuil de similarité |
@Search.ranking | #HIGH, #MEDIUM, #LOW | Priorité dans les résultats |
Combinaison avec les filtres
La recherche générique complète, mais ne remplace pas les filtres :
@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}Conclusion
La recherche générique dans RAP offre une manière puissante et déclarative pour des fonctions de recherche conviviales :
| Aspect | Recommandation |
|---|---|
| Activation | @Search.searchable: true sur la vue |
| Champs | 5-8 champs métier pertinents |
| Fuzziness | 1.0 pour les IDs, 0.8 pour les noms |
| Ranking | #HIGH pour les clés primaires |
| Performance | Index, nombre de champs limité |
Avec quelques annotations, vous obtenez une fonction de recherche professionnelle permettant aux utilisateurs de trouver rapidement des données.
Articles complémentaires
- RAP Grundlagen - Introduction à RESTful ABAP Programming
- CDS Annotations - Aperçu de toutes les annotations
- RAP Value Helps - Aides à la saisie pour les champs de filtre
- RAP CDS Pattern - Architecture RAP simplifiée