首页 > 解决方案 > 如何获取 OData (V2) 属性的聚合值?

问题描述

我想显示一个图表 ( sap.viz.ui5.controls.VizFrame),它将 OData 服务中的数据可视化。但是,必须对服务的数据进行操作。请参见下面的示例:

主视图.xml

<mvc:View controllerName="demo.chart.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Chart Demo">
                    <content></content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

Chart.fragment.xml

<c:FragmentDefinition xmlns:c="sap.ui.core" xmlns:viz="sap.viz.ui5.controls" xmlns:viz.data="sap.viz.ui5.data"
    xmlns:viz.feeds="sap.viz.ui5.controls.common.feeds">
    <viz:VizFrame uiConfig="{applicationSet:'fiori'}" vizType='donut'>
        <viz:dataset>
            <viz.data:FlattenedDataset data="{manipulatedData>/}">
                <viz.data:dimensions>
                    <viz.data:DimensionDefinition name="Gender" value="{manipulatedData>gender}"/>
                </viz.data:dimensions>
                <viz.data:measures>
                    <viz.data:MeasureDefinition name="Amount" value="{manipulatedData>amount}"/>
                </viz.data:measures>
            </viz.data:FlattenedDataset>
        </viz:dataset>
        <viz:feeds>
            <viz.feeds:FeedItem uid="color" type="Dimension" values="Gender"/>
            <viz.feeds:FeedItem uid="size" type="Measure" values="Amount"/>
        </viz:feeds>
    </viz:VizFrame>
</c:FragmentDefinition>

主控制器.js

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/model/json/JSONModel",
    "sap/ui/core/Fragment"
], function (Controller, JSONModel, Fragment) {
    "use strict";

    return Controller.extend("demo.chart.controller.Main", {
        onInit: function () {
            const mDefault = this.getOwnerComponent().getModel();
            const mManipulatedData = new JSONModel([{
                gender: "F",
                amount: 0
            }, {
                gender: "M",
                amount: 0
            }, {
                gender: "X",
                amount: 12
            }]);
            this.getView().setModel(mManipulatedData, "manipulatedData");

            console.log(this.getView().getModel("manipulatedData"));

            mDefault.read("/ContactSet", {
                success: oData => {
                    const aManipulatedData = mManipulatedData.getData();

                    oData.results.forEach(entry => {
                        aManipulatedData.forEach(type => {
                            if (entry.Sex === type.gender) {
                                type.amount++
                            }
                        })
                    });

                    Fragment.load({
                        name: "demo.chart.view.Chart",
                        controller: this
                    }).then(oFragment => {
                        this.getView().addDependent(oFragment);
                        this.byId("page").addContent(oFragment);
                    });
                }
            })
        }
    });
});

服务结构 ( GWSAMPLE_BASIC/ContactSet)

{
    "d": {
        "results": [
            {
                "__metadata": {
                    "id": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')",
                    "uri": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')",
                    "type": "GWSAMPLE_BASIC.Contact"
                },
                "Address": {
                    "__metadata": {
                        "type": "GWSAMPLE_BASIC.CT_Address"
                    },
                    "City": "Walldorf",
                    "PostalCode": "69190",
                    "Street": "Robert-Koch-Straße",
                    "Building": "1",
                    "Country": "DE",
                    "AddressType": "02"
                },
                "ContactGuid": "0050568c-901d-1eda-bcae-e8394de7e116",
                "BusinessPartnerID": "0100000000",
                "Title": "",
                "FirstName": "Karl",
                "MiddleName": "",
                "LastName": "Müller",
                "Nickname": "",
                "Initials": "",
                "Sex": "M",
                "PhoneNumber": "0622734567",
                "FaxNumber": "0622734004",
                "EmailAddress": "do.not.reply@sap.com",
                "Language": "EN",
                "DateOfBirth": null,
                "ToBusinessPartner": {
                    "__deferred": {
                        "uri": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')/ToBusinessPartner"
                    }
                }
            }
        ]
    }
}

因此,如您所见,我只对Sex属性的聚合值感兴趣。我当前的解决方案是遍历实体集的所有条目并增加自定义 JSON 模型中的属性。这不仅性能不佳,因为您在客户端进行繁重的工作,而且还要求您立即了解图表中显示的数据的所有可能值。有没有办法通过 OData 查询来做到这一点,或者我是否必须使用我的 SAP 系统中的计算数据创建一个新实体集?

标签: sapui5

解决方案


OData 应该能够计数和分组,如本问题所述:OData v4 groupby with $count

但我怀疑您的 SAP OData 服务在大多数情况下不会实现完整的 OData 规范。

您可以通过不使用两个嵌套的 for 循环来改进您的 js,但如下所示:

mGender = {};
oData.results.forEach(entry => {
    if (!mGender[entry.Sex])
        {mGender[entry.Sex] = 0
    }
    mGender[entry.Sex]++
});

推荐阅读