平时做Fiori项目,问得最多的问题往往不是复杂的增强开发,而是最简单的“用户找不到东西”。要么是“采购申请单在哪个App里查”,要么是“我明明记得销售订单号,但就是不知道用哪个应用能看到”,再要么是用户对着一整页Tile翻来翻去找不到入口。每次遇到这种场景我都觉得可惜:SAP Fiori的搜索能力其实很强,但很多项目上线时只配了角色、分配了Tile,搜索模块基本没调,结果本该提升效率的入口变成了最大的效率短板。
本文想围绕“SAP Fiori搜索”这件事,把两条平行的检索路径讲透:一条是业务对象检索,也就是直接搜订单、客户、物料这些具体业务数据;另一条是应用入口检索,也就是从几十上百个Tile里快速定位到某个Fiori应用。两条路径配置思路不同、技术原理不同、踩坑点也不同,但只有一起配好,用户的Fiori体验才算真正立起来。文章适合正在做Fiori实施/运维的顾问、系统管理员,也适合负责推广Fiori的业务Key User。
1. 先想清楚:Fiori搜索的“两层结构”到底指什么
1.1 入口搜索与业务对象搜索的本质区别
很多初次接触Fiori的人会把“搜索”当成一件事,其实是两件事。
第一件事是“找应用”。用户知道有个App叫“销售订单列表”,但不知道它在哪个组哪个位置,于是直接在Launchpad右上角的搜索框里输入“销售订单”。这时候系统匹配的是Tile的元数据——标题、副标题、关键词,本质上是拿用户输入和Catalog里登记的条目做比对。这类搜索我习惯叫入口搜索,它的核心是“App发现”。
第二件事是“找数据”。用户已经打开了App,在List Report的搜索框里输入一个订单号,或者输入客户名称的一部分,系统去后端OData服务里执行$search,把满足条件的业务数据查出来。这类搜索是业务对象搜索,核心是“数据检索”。
两者用的搜索词相同,但背后的数据源、索引方式、权限模型完全不一样。入口搜索匹配的是目录元数据,业务对象搜索匹配的是业务表字段。如果不把这两条链路分开理解,后面配置起来很容易混乱,这也是很多项目搜索调不好的根因。
1.2 FLP搜索框背后发生了什么
打开Fiori Launchpad,右上角的放大镜图标就是默认的全局搜索入口。用户输入关键词后,结果列表会按来源分组,常见的有“Apps”“Business Data”等分组。Apps分组就是刚才说的入口搜索,它读取的是Fiori目录中已分配Tile的描述信息;Business Data分组则是业务对象搜索的结果,通常来自已注册的可搜索数据源。
在S/4HANA环境下,业务数据源通常依托CDS视图加OData服务暴露。用户在一个输入框里既完成了“找到哪个App”,又完成了“预览相关业务数据”,这就是Fiori搜索比较理想的状态。但实际配置过程中,Business Data分组常常是空的,因为管理员根本没把可搜索业务对象注册进去。
另外需要注意,这个全局搜索框和App列表页内的搜索框不是同一个东西。全局搜索框是跨应用的数据发现入口,App列表页内的搜索框是当前应用内部的过滤工具。二者能力有重叠,但定位不同。
1.3 为什么很多项目搜索配不好
我见过太多项目,上线接近尾声才想到搜索,然后把所有搜索问题都归结为“给Tile填个关键词”。结果就是入口搜索勉强能用,业务对象搜索完全没配;或者反过来,List Report里的搜索框明明有,但搜出来一堆无关数据,用户很快就放弃搜索功能,退回“翻菜单”的老路。
搜索没配好,通常有几种典型原因:一是压根没建可搜索CDS视图,业务数据没有暴露给搜索框架;二是配置了搜索字段但没区分主次,所有字段都可搜索,导致结果宽泛且性能差;三是权限没跟上,用户能打开App但搜不到数据,或者反过来,搜索建议里出现了用户无权访问的数据;四是缓存和索引问题,App配置改了但搜索结果迟迟不更新。
这些坑后面都会讲到。配置Fiori搜索不复杂,但每一步都要知道为什么这么做,否则出问题根本无从下手。
2. 业务对象级检索:让用户直接命中业务事实
2.1 用CDS View给业务对象打开搜索开关
先把最核心的一步讲清楚:要让一个业务对象能被Fiori搜索命中,首先得让这个对象“可以被搜索”。在S/4HANA中,最常见的方式是在CDS视图上添加@Search.searchable: true注解。
拿销售订单举例,标准系统中有一个核心视图I_SalesOrder,我们可以基于它创建一个自定义视图,把关键字段暴露出来:
@Search.searchable: true define view Z_I_SalesOrder as select from I_SalesOrder as so { key so.SalesOrder, so.CompanyCode, so.SoldToParty, so.TotalNetAmount, so.OverallSDProcessStatus }这个注解的作用是告诉Fiori框架:这个CDS视图对应一个可搜索的业务对象。后续在OData服务发布、Fiori Elements应用生成时,框架就会为该视图生成对应的搜索行为。
这里有个实操建议:不要图省事把一个大视图的所有字段全部设为可搜索。搜索字段越多,后端生成的SQL越复杂,用户搜起来越慢。我一般只挑3到5个用户真正会用来检索的字段,比如单据编号、客户编号、日期范围、状态字段,其余字段保持普通展示即可。
2.2 搜索字段、默认搜索元素与模糊度配置
给CDS视图标了@Search.searchable之后,还需要细化到字段级别。以销售订单的“订单号”为例:
@Search.defaultSearchElement: true @Search.fuzziness: 0.7 so.SalesOrder, @Search.defaultSearchElement: true @Search.fuzziness: 0.8 so.SoldToParty,@Search.defaultSearchElement表示该字段是默认搜索元素。用户在Fiori Elements的搜索框里直接输入关键词时,系统只在这些默认元素中匹配;如果没有标注任何默认搜索元素,系统才会退回到所有可搜索字段中查找。这个配置直接决定搜索的精准度。
@Search.fuzziness控制模糊程度,取值范围0到1。值为0.9表示要求比较高,只有比较接近的匹配才会返回;值为0.6则更宽松,适合搜索客户名称这种可能有拼写变体的字段。订单号这种结构化编号,我倾向调高到0.8以上,避免搜一个编号返回一堆相似编号。
另外提一下,Fiori Elements List Report里的搜索框支持结构化搜索条件。用户点开搜索框旁边的漏斗图标,会看到SelectionFields。这个不是自动生成的,需要在界面注释中显式声明,常用的也是那几个搜索字段。
2.3 搜索帮助:让搜索条件和业务含义对得上
不少业务对象的标准字段是编码,比如“客户编号”是10位字符串,但用户记忆里的是客户名称。如果只允许按编号搜,搜索体验就很差。这时候需要引入搜索帮助,把编号和描述串起来。
在CDS视图里,可以通过@Consumption.valueHelpDefinition绑定一个值帮助。以下是我常用的配置方式:
@Consumption.valueHelpDefinition: [{ entity: { name: 'I_Customer', element: 'Customer' } }] so.SoldToParty,这样用户在搜索字段里选择“客户”时,会弹出一个值帮助对话框,可以按客户名称模糊筛选,选中的值再回填到SoldToParty字段里。
搜索帮助和全文模糊搜索是两种互补的能力。全文搜索适合快速模糊查找,搜索帮助适合需要精确限定条件、或者跨字段关联查找的场景。项目里通常两者都要配:搜索框负责“快速搜一把”,搜索帮助负责“精准筛一遍”。
2.4 权限与数据可见性控制
业务对象搜索如果不能和权限联动,是个很大的隐患。用户拿到一个搜索建议列表,点进去却报“无权查看”,体验很差;反过来,如果搜索接口没做权限过滤,用户可能通过构造请求搜到不该看的数据。
在使用CDS视图作为搜索数据源时,权限控制通常依赖DCL(Data Control Language)。CDS视图上如果做了权限注解,OData服务执行$search时会自动应用数据权限过滤。这里的重点是:发布服务时要确认权限上下文已经被带上,而不是仅仅验证了功能权限。
我在项目中会做一组专项测试:用一个有“创建销售订单”但没有“查看所有公司代码”权限的账号,去搜索不同公司代码的订单,验证返回结果是否被正确裁剪。这一步千万别省,权限问题在搜索场景里比普通列表页更容易被忽略。
3. 应用入口级检索:让用户从几十个Tile里快速定位App
3.1 Tile元数据:标题、副标题、关键词怎么填
业务对象搜索解决的是“数据在哪”的问题,应用入口搜索解决的是“App在哪”的问题。入口搜索的配置核心,是Fiori Launchpad的Tile元数据。
在Fiori Launchpad Designer里创建App Launcher Tile时,最显眼的配置项是Title和Subtitle。比如Title填“销售订单列表”,Subtitle填“按客户、日期、状态查询销售订单”。这两个字段会显示在Tile表面,同时也是入口搜索的匹配对象。
容易被忽略的是Keywords字段。Keywords不会直接显示在Tile上,但会参与搜索匹配。我的习惯是把用户日常会用的各种叫法、俗称、甚至是内部缩写都维护进去。比如一个“物料主数据查询”的App,Keywords里除了“物料主数据”,还可以加“MM03”“物料基础数据”“Material Master”等。这样无论用户按中文、英文还是事务代码记忆去搜,都能命中。
需要特别提醒:Keywords不要乱填,不要为了搜索命中率把无关词都塞进去。搜索本质上是把用户输入和元数据做匹配,如果Keywords和Tile实际功能对不上,用户搜到了但打开发现不是自己要用的,信任度反而会下降。
3.2 Semantic Object与Action:搜索背后的导航语义
Fiori里有一层经常被忽略的搜索语义,就是Semantic Object和Action。一个Fiori App在manifest.json中会注册自己的语义对象和动作,比如:
"sap.app": { "crossNavigation": { "targets": { "SalesOrderDisplay": { "semanticObject": "SalesOrder", "action": "display" } } } }这套语义配置有两个作用。第一,它是跨应用导航的“地址”,其他App可以通过语义对象+动作跳转到这个App;第二,它会被Fiori的入口搜索索引,用户在全局搜索框输入“SalesOrder”时,相关的App会出现在结果里。
很多自定义App开发时,开发者只关注页面功能,manifest.json里的语义配置随便填甚至不填,结果就是入口搜索匹配不到。建议在开发规范里明确要求:每个自定义Fiori App必须填写有业务含义的semanticObject和action,不要用“ZAPP1”“test”这种无意义命名。
3.3 自定义搜索标签:解决俗称“别名”的检索需求
入口搜索体验做到位,往往不是靠Title,而是靠“别名”。同一个业务对象,销售部门叫“销售订单”,物流部门叫“出货单”,财务部门可能叫“收入确认单”。如果只维护一个名字,搜索结果会漏掉大量潜在用户。
我的做法是建一张“搜索词表”来维护别名。具体落地时,就是把收集到的别名统一维护到Tile的Keywords字段中。比如“销售订单查询”这个App,Keywords可以维护成“SO、销售订单、订单查询、SA订单、sales order”。
这个工作建议在项目上线前做一个专项收集会,把各模块的关键用户叫过来,问他们平时怎么称呼这些业务对象,然后统一整理成表,分模块录入。这个动作投入不大,但对一线用户感知的提升非常明显。
3.4 多语言环境下的入口搜索配置
Fiori是国际化产品,一个系统里可能有中文用户、英文用户、甚至其他语言的用户。入口搜索在不同语言环境下,匹配的是对应语言的Tile元数据。
也就是说,如果系统里只有英文用户,Tile的Title维护中文,这些用户在英文界面下大概率搜不到。SAP标准应用基本已经做好了多语言翻译,但自定义Tile不一样,需要在每个语言环境下维护Title、Subtitle和Keywords。
多语言维护我建议不要直接在前端界面里一条条改,而是把Keywords等文本资源放到翻译请求里统一管理。这样的好处是:翻译人员可以批量处理,而且语言包更新时不会覆盖手工修改。
4. 实操记录:从业务对象到应用入口的一次完整配置
4.1 准备基础对象与OData服务
前面讲了不少原理,这部分把一次完整的配置流程串起来,按照一个销售订单查询场景从头到尾过一遍。
第一步,在ABAP开发环境里创建CDS视图。我用的是基于I_SalesOrder的自定义视图,加上@Search.searchable: true和各字段的搜索注解。开发完激活后,紧跟着做的是RAP Service的行为定义,把销售订单的查询逻辑暴露成OData服务。
如果是标准Fiori Elements应用,这一步可以利用RAP Generator基于CDS视图直接生成Service和UI。生成完之后,在/IWFND/MAINT_SERVICE事务码里激活服务,并通过浏览器访问$metadata确认搜索相关注解已经正确暴露到OData元数据中。
4.2 实现业务对象搜索
服务激活后,用Fiori Elements的Preview功能打开应用,先测List Report里的搜索框。输入一个订单号,观察网络请求,正常的请求会携带$search=参数。这一步能确认OData服务的搜索能力已经生效。
随后检查返回结果是否和预期一致。如果搜索框输入“10000001”但返回了所有订单,那就要回CDS视图检查@Search.defaultSearchElement是否标注正确。如果返回结果没有按客户名称命中,检查是否漏了搜索帮助或者该字段没有被标记为可搜索。
最后在FLP全局搜索里验证业务数据分组。如果S/4HANA的Search Model配置正常,输入订单号时可以看到该业务对象的建议条目;如果看不到,排查搜索模型是否已发布、当前用户角色是否包含对应Catalog。
4.3 配置应用入口与搜索标签
业务数据部分通了之后,再去配置入口搜索。在Fiori Launchpad Designer里,找到“销售订单查询”这个App对应的Tile,把Title、Subtitle、Keywords以及语义对象、动作按前面说的规则填好。
Keywords我是按这样维护的:销售订单、订单查询、SO查询、Sales Order Query。Subtitle不要写废话,写清楚这个App能干什么,比如“按订单编号、客户、日期范围查询销售订单以及查看行项目”。
如果这个App还需要从其他App被导航跳转,一定要把semanticObject和action配套好,并在跨应用导航的消费方配置好目标参数。
4.4 联调验证
配置完成后,先用管理员账号做一轮验证。在FLP搜索框里分别输入:完整标题、标题片段、Keywords别名、业务对象编码,确认不同输入方式都能命中目标App。再切到普通业务用户账号,确认搜索结果在角色分配范围内可见,且无权访问的App不会出现在结果里。
接着验证数据搜索。输入一个具体订单号,确认全局搜索的业务数据建议能显示;点击跳转到对应App后,确认列表已通过默认筛选条件定位到目标单据。这两层搜索都通了,才算真正完成了“从业务对象到应用入口”的闭环。
5. 常见问题与排查手册
5.1 新App半天搜不到
这是上线后最常遇到的投诉。一个新App已经分配了角色,用户在自己的Launchpad上能看到Tile,但在搜索框里输入名称却搜不到。
碰到这种情况,先别急着怀疑搜索配置,按顺序排查:第一,检查Tile是不是激活状态;第二,检查Catalog有没有被分配进用户的业务角色;第三,检查FLP缓存是否刷新。尤其第三种,很多问题不是配置错了,而是Fiori Launchpad的客户端缓存还停留在旧状态。
处理方式是让用户在Launchpad右上角的“用户设置”里清空缓存,或者管理员在后端刷新ICM和Gateway缓存。如果还不行,再回去检查Tile的Title和Keywords是否维护在正确语言环境。
5.2 搜索不到业务数据但App能打开
用户能正常打开App,能用列表自带过滤条件查到数据,但在FLP全局搜索里搜不到对应业务数据。这个问题大概率出在搜索模型或Index的同步上。
全局搜索里的业务数据分组,并不是实时查所有数据库表,而是读取预先构建的搜索索引或搜索模型。CDS视图更新了、新数据加了索引但索引没有重建,就会出现“库里明明有,搜索搜不到”的情况。
处理思路是到搜索模型配置里检查该业务对象的搜索状态,必要时重建搜索索引。另外注意,业务对象搜索对权限过滤很敏感,如果当前用户权限范围和数据实际归属不一致,也可能出现搜索结果为空的现象。
5.3 搜索慢或超时
搜索请求慢,先看是不是可搜索字段太多。我在项目里见过一个CDS视图,把几十个字段全部标成可搜索,结果每个搜索请求都要对多个字段做模糊匹配,几百毫秒的请求直接变成好几秒。
解决办法有两个方向:一是收窄默认搜索元素,让用户不带条件搜索时只在3到5个核心字段上跑;二是在HANA层面对高频搜索字段建立全文索引。对于数据量特别大的表,还可以在CDS视图里限制搜索只能在特定组织范围内进行,减少扫描数据量。
5.4 中文/特殊字符搜索不准
中文环境下的Fiori搜索,经常遇到“输入中文搜不到,输入编码能搜到”的现象。原因多半出在HANA全文索引的语言配置上。中文字符串不像英文有天然空格分词,索引如果没有正确启用中文分词,模糊匹配效果会大打折扣。
遇到这种情况,先去HANA数据库检查该表的全文索引定义,确认语言配置正确。对于特殊字符,比如订单号里带斜杠、百分号,要注意OData搜索时这些字符可能被当作通配符或转义符处理,必要时在后台搜索逻辑中做字符转义。
最后再分享一个小技巧
搜索配置全部上线之后,不要以为就完事了。我习惯上线后隔两到四周,让系统管理员导出用户的实际搜索词,看看哪些词高频但搜索结果“无命中”。把这些词整理出来,和现有Tile的Keywords做对照,能发现很多用户真实的叫法和我们预想的完全不一样。把这些词补进Keywords,再观察一段时间,入口搜索的命中率会有非常明显的提升。Fiori搜索这件事,做好一次配置只是起点,持续根据真实使用数据微调,才能让用户真正觉得“搜索比翻菜单快”。