CAP自定义事件处理程序和OData查询

2020-08-24 11:33发布

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


你好

我目前正在使用CAP和Node.js开发应用程序。 该应用程序基本上是一项服务,可聚合来自现有标准SAP API和Fiori Elements前端(列表报告和对象页面)的数据。

为了能够汇总API的数据,我使用Javascript中的自定义服务实现以及事件处理程序(之前,之后,之后)。

我的问题是,我无法重新实现OData V4 $ count查询(在自定义处理程序中),这对于使Fiori Elements列表报表起作用是必需的。 显然,自定义处理程序会"覆盖"标准$ count处理程序? 因此,列表报告发出以下请求:

 READ实体{
   '$ count':'true',
   '$ select':'...',
   '$ skip':'0',
   '$ top':'30'
 } 

但是得到以下答案:

" @ odata.context":" $ metadata#Entity",
   " @ odata.metadataEtag":" ...",
   " @ odata.count":0,
   "值":[
     {...},{...},...
   ] 

由于@ odata.count值为0,因此列表报告不显示任何数据。 我找不到在自定义处理程序中设置此值的任何方法,因为似乎我只能访问"值"数组。

所以我的问题是:是否可以为结果数组设置自定义值,并且仍然可以使用标准的OData处理程序

我的问题专门针对$ count查询,但我也想避免尽可能地重新编码$ filter和$ sort逻辑。

这是我当前的实现示例:

 srv.on('READ','Entity',async(req)=> {
 const queryOptions = req ._。odataReq.getQueryOptions()||  {};

 const [data1,data2,data3] =等待Promise.all([
 srv.run(SELECT.from('Entity1')),
 srv.run(SELECT.from('Entity2')),
 srv.run(SELECT.from('Entity3')),
 ]);
 const elements = [... data1,... data2,... data3]
 .map((el)=>({Prop1:el.Prop1,Prop2:el.Prop2,Prop3:el.Prop3}));

 const reqData = req.data;
 如果(reqData && reqData.Prop1 && reqData.Prop3){
 const element = elements.find((el)=> el.Prop1 === reqData.Prop1 && el.Prop3 === reqData.Prop3);
 返回元素;
 }
 const top = queryOptions。$ top ||  flow.length;
 const skip = queryOptions。$ skip ||  0;
 返回elements.slice(skip,(skip + top <= elements.length?skip + top:elements.length));
 });

 srv.after('READ','Entity',async(results,req)=> {
 const queryOptions = req ._。odataReq.getQueryOptions();
 如果(queryOptions && queryOptions。$ expand){
 如果(!Object.keys(req.data).length){
 req.reject(501,'未实现');
 } else if(results.length){
 const el = results [0];
 const items = await srv.run(SELECT.from('EntityItems')。where({Entity_Prop1:el.Prop1,Entity_Prop3:el.Prop3}));
 el.Items =项目;
 }
 }
 });

 srv.on('READ',['Entity1','Entity2','Entity3'],async(req)=> {
//处理对外部API的请求
 }):
 

感谢您的帮助,

西奥

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


你好

我目前正在使用CAP和Node.js开发应用程序。 该应用程序基本上是一项服务,可聚合来自现有标准SAP API和Fiori Elements前端(列表报告和对象页面)的数据。

为了能够汇总API的数据,我使用Javascript中的自定义服务实现以及事件处理程序(之前,之后,之后)。

我的问题是,我无法重新实现OData V4 $ count查询(在自定义处理程序中),这对于使Fiori Elements列表报表起作用是必需的。 显然,自定义处理程序会"覆盖"标准$ count处理程序? 因此,列表报告发出以下请求:

 READ实体{
   '$ count':'true',
   '$ select':'...',
   '$ skip':'0',
   '$ top':'30'
 } 

但是得到以下答案:

" @ odata.context":" $ metadata#Entity",
   " @ odata.metadataEtag":" ...",
   " @ odata.count":0,
   "值":[
     {...},{...},...
   ] 

由于@ odata.count值为0,因此列表报告不显示任何数据。 我找不到在自定义处理程序中设置此值的任何方法,因为似乎我只能访问"值"数组。

所以我的问题是:是否可以为结果数组设置自定义值,并且仍然可以使用标准的OData处理程序

我的问题专门针对$ count查询,但我也想避免尽可能地重新编码$ filter和$ sort逻辑。

这是我当前的实现示例:

 srv.on('READ','Entity',async(req)=> {
 const queryOptions = req ._。odataReq.getQueryOptions()||  {};

 const [data1,data2,data3] =等待Promise.all([
 srv.run(SELECT.from('Entity1')),
 srv.run(SELECT.from('Entity2')),
 srv.run(SELECT.from('Entity3')),
 ]);
 const elements = [... data1,... data2,... data3]
 .map((el)=>({Prop1:el.Prop1,Prop2:el.Prop2,Prop3:el.Prop3}));

 const reqData = req.data;
 如果(reqData && reqData.Prop1 && reqData.Prop3){
 const element = elements.find((el)=> el.Prop1 === reqData.Prop1 && el.Prop3 === reqData.Prop3);
 返回元素;
 }
 const top = queryOptions。$ top ||  flow.length;
 const skip = queryOptions。$ skip ||  0;
 返回elements.slice(skip,(skip + top <= elements.length?skip + top:elements.length));
 });

 srv.after('READ','Entity',async(results,req)=> {
 const queryOptions = req ._。odataReq.getQueryOptions();
 如果(queryOptions && queryOptions。$ expand){
 如果(!Object.keys(req.data).length){
 req.reject(501,'未实现');
 } else if(results.length){
 const el = results [0];
 const items = await srv.run(SELECT.from('EntityItems')。where({Entity_Prop1:el.Prop1,Entity_Prop3:el.Prop3}));
 el.Items =项目;
 }
 }
 });

 srv.on('READ',['Entity1','Entity2','Entity3'],async(req)=> {
//处理对外部API的请求
 }):
 

感谢您的帮助,

西奥

付费偷看设置
发送
3条回答
能不能别闹
1楼-- · 2020-08-24 12:24

你好,

大多数查询选项(例如$ filter和$ sort)被推送到数据库,而不应用于自定义处理程序返回的结果集。 因此,您必须亲自应对。 对于$ filter来说,它实际上非常简单,因为它们导致独立的where语句,您可以将这些语句传递给所有三个远程服务(参见fluent QL API SELECT.from(...)。where({...}))。 对于像$ sort,$ top和$ skip这样的其他对象,则不必太多,因为必须将它们应用于合并结果集。

在当前版本为CAP的情况下,查询选项$ count的处理方式类似于读取请求。 如果有内联计数,它将触发应用程序内的第二次读取。 也就是说,GET .../Books/$ count是单个READ事件,GET .../Books?$ count = true导致两个单独的READ事件,即一个用于获取数据和一个用于获取计数。 第二个事件的on处理程序(检查req ._。odataReq以区分两者)需要返回格式[{count:}],该格式又填充属性@ odata.count。

最好,塞巴斯蒂安(Sebastian)

小c菟菟
2楼-- · 2020-08-24 12:18

您好,

也许您可以在GitHub上共享一个示例项目来说明问题?

最好的问候
格雷戈尔

小灯塔
3楼-- · 2020-08-24 12:23

你好塞巴斯蒂安,

非常感谢,我能够做到这一点。

对于任何想知道的人,下面是一个示例代码,可以集成到srv.on('READ',...)处理程序中,以处理$ count = true查询选项和.../$ count查询:

 if(req ._。odataReq._url.path.includes('/$ count')|| req.query.SELECT.columns [0] .func ==='count'){
      返回[{计算:elements.length}];
 } 

(请注意,可能有更清洁的方法来做到这一点)

Théo

一周热门 更多>