Recherche générique dans RAP : Annotations @Search pour Fiori Elements

Catégorie
RAP
Publié
Auteur
Johannes

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: true
define 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: 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
}

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

ValeurSignificationExemple : Recherche “Müller”
1.0ExactUniquement “Müller”
0.9Presque exact”Müller”, “Mueller”
0.8Tolérant (Standard)“Müller”, “Mueller”, “Muller”, “Müler”
0.7Très tolérantAussi “Miller”, “Meller”

Fuzziness dans le 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
}

Quelle Fuzziness pour quel type de champ ?

Type de champFuzziness recommandéeJustification
IDs, Codes1.0Correspondance exacte requise
Noms0.7 - 0.8Tenir compte des fautes de frappe, umlauts
Villes, Pays0.85 - 0.9Permettre des variantes légères
Descriptions0.7 - 0.8Plus flexible pour le texte libre
Adresses e-mail1.0Exact

Ranking : Prioriser les résultats de recherche

Le Ranking détermine quels résultats sont affichés en premier :

@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
}

Niveaux de Ranking

NiveauUtilisation
#HIGHIdentifiants primaires (IDs, numéros)
#MEDIUMChamps métier importants (noms, désignations)
#LOWInformations 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: 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
}

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: 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
}

Considérations de performance

Indexation

Les champs interrogeables doivent être indexés dans la base de données :

-- 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);
}

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: true
BookingId,
@Search.defaultSearchElement: true
CustomerName,
@Search.defaultSearchElement: true
DepartureCity,
@Search.defaultSearchElement: true
ArrivalCity,
@Search.defaultSearchElement: true
CarrierId

Grands 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äge

Pour de grands volumes de données, désactivez la recherche automatique lors de la saisie et forcez la recherche explicite.

AnnotationValeursDescription
@Search.searchabletrue/falseActive la recherche au niveau de la vue
@Search.defaultSearchElementtrue/falseLe champ est interrogeable
@Search.fuzzinessThreshold0.0 - 1.0Seuil de similarité
@Search.ranking#HIGH, #MEDIUM, #LOWPriorité dans les résultats

Combinaison avec les filtres

La recherche générique complète, mais ne remplace pas les filtres :

@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
}

Conclusion

La recherche générique dans RAP offre une manière puissante et déclarative pour des fonctions de recherche conviviales :

AspectRecommandation
Activation@Search.searchable: true sur la vue
Champs5-8 champs métier pertinents
Fuzziness1.0 pour les IDs, 0.8 pour les noms
Ranking#HIGH pour les clés primaires
PerformanceIndex, 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