如何将SAPUI5 OData在绑定到客户端控制之前?

时间:2023-02-13 16:21:09

I have an odata list for example in JSON notation:

我有一个用JSON表示的odata列表:

var data = [
 {"category" : "A", "value" : 1, "group" : "x"},
 {"category" : "B", "value" : 2, "group" : "y"},
 {"category" : "C", "value" : 3, "group" : "x"},
 {"category" : "A", "value" : 4, "group" : "y"},
 {"category" : "A", "value" : 5, "group" : "x"}
];

First of all I filter against group == x; Values left are:

首先,我过滤组== x;左值是:

var data = [
 {"category" : "A", "value" : 1, "group" : "x"},
 {"category" : "C", "value" : 3, "group" : "x"},
 {"category" : "A", "value" : 5, "group" : "x"}
];

Now I would group (at client side) by category and sum up the values, so the result should be:

现在我将(在客户端)按类别进行分组并对值进行汇总,结果应该是:

var data = [
 {"category" : "A", "value" : 6, },
 {"category" : "C", "value" : 3, },
];

After that I would bind the model to some SAPUI5 control.

之后,我将模型绑定到一些SAPUI5控件。

But the grouping part seems not possible.

但分组似乎是不可能的。

Does someone know a generic solution for that problem?

有人知道这个问题的通用解决方案吗?

A potential use case:

一个潜在的用例:

var oDataset = new sap.viz.ui5.data.FlattenedDataset({
    dimensions : [ {axis : 1, value : "{category}", name : "Category" } ],
    measures : [ {value : "{value}", name : "Value" } ],
    data : {
        path : "/Data"
    }
});

var oGraph = new sap.viz.ui5.Donut({
    dataset : oDataset, // sap.viz.ui5.data.Dataset
});

2 个解决方案

#1


6  

The following code works for me. Query Northwind Order_Details service for a couple of Products via a generic binding, map reduce the the returned bindings and aggregate the Quantity of each order to the total Quanity sold, show the results in a column chart.

下面的代码对我有用。查询Northwind Order_Details服务通过一个通用绑定,映射减少返回的绑定,并将每个订单的数量汇总到所销售的全部数量,并在列图表中显示结果。

see jsBin Example

看到jsBin例子

note sap.viz introduces Array.prototype.map and Array.prototype.reduce functions

注意sap.viz介绍Array.prototype。地图和Array.prototype。减少功能

var sURI = 'http://services.odata.org/Northwind/Northwind.svc/';
var oDataModel = new sap.ui.model.odata.ODataModel(sURI, true);
oDataModel.setSizeLimit(10000);
var oJSONModel = new sap.ui.model.json.JSONModel({}, 'jmodel');

// handle list of contexts
var handler = function(oEvent) {
    var mapCallback = function(oContext) {
        var obj = {};
        obj.ProductID = oContext.getObject().ProductID,
        obj.Quantity = oContext.getObject().Quantity
        return obj;
    };

    var reduceCallback = function(aPrev, oCurr) {
        var aNext = aPrev;
        var bFound = false;

        aNext.forEach(function(item) {
            if (item.ProductID === oCurr.ProductID) {
                bFound = true;
                item.Quantity += oCurr.Quantity;
            }
        })

        if (bFound === false) {
            aNext.push(oCurr);
        }

        return aNext;
    };
    //release handler
    oBindings.detachChange(handler);

    var aTotals = oEvent.oSource.getContexts().map(mapCallback).reduce(reduceCallback, []);
    oJSONModel.setData({
        'Order_Totals': aTotals
    });
};

// Filter all orders by 3 products
var oFilter1 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '1');
var oFilter2 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '68');
var oFilter3 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '11');
var aFilter = [oFilter1, oFilter2, oFilter3];

// Sort by ProductID
var oSorter = new sap.ui.model.Sorter("ProductID", false, true);

// Reduce the returned payload by nominating need fields
var oSelect = {
    select: 'ProductID,Quantity'
}

var oBindings = oDataModel.bindList("/Order_Details", null, oSorter, aFilter, oSelect);

// call OData service and handle results
oBindings.attachChange(handler);
oBindings.getContexts();

var oDataset = new sap.viz.ui5.data.FlattenedDataset({
    dimensions: [{
        axis: 1,
        name: 'ProductID',
        value: "{ProductID}"
    }],
    measures: [{
        name: 'Quantity Sold',
        value: '{Quantity}'
    }],
    data: {
        path: "/Order_Totals"
    }
});

var oColumnChart = new sap.viz.ui5.Column({
    width: "80%",
    height: "400px",
    plotArea: {
        'colorPalette': d3.scale.category20().range()
    },
    title: {
        visible: true,
        text: 'Qutantity Sold by Product'
    },
    dataset: oDataset
});

oColumnChart.setModel(oJSONModel);

#2


1  

For your final result i have written a code. Although it is not fully optimized but it works fine.

对于你的最终结果,我写了一段代码。虽然它不是完全优化的,但是它工作得很好。

Here is your full code

这是您的全部代码

var data = [
 {"category" : "A", "value" : 1, "group" : "x"},
 {"category" : "B", "value" : 2, "group" : "y"},
 {"category" : "C", "value" : 3, "group" : "x"},
 {"category" : "A", "value" : 4, "group" : "y"},
 {"category" : "A", "value" : 5, "group" : "x"}
];

function groupBy( array , f )
{
  var groups = {};
  array.forEach( function( o )
  {
    if(o.group=="x")
    {
        var group = JSON.stringify( f(o) );
        groups[group] = groups[group] || [];
        groups[group].push( o );
    }

  });
  return Object.keys(groups).map( function( group )
  {
    return groups[group]; 
  })
}
var groupByGroup = groupBy(data, function(item)
{
  return [item.group];
});
var groupByCategory = groupBy(groupByGroup[0], function(item)
{
  return [item.category];
});
getData(groupByCategory);

function getData(groupByCategory)
{
  var  finalData=[];
    for(var i=0;i< groupByCategory.length;i++)
    {
    var temp=0;
        for(var j=0;j<groupByCategory[i].length;j++)
        {
            temp+=parseInt(groupByCategory[i][j].value);
        }
        finalData.push({"category":groupByCategory[i][0].category, "value":temp})
    }
    console.log(finalData);//final data is your required results
}

If you want to compare using two parameter .Suppose you want to compare by category as well as group then in groupByGroup function you have to write as follow

如果您想使用两个参数进行比较,假设您想要按类别和组进行比较,那么在groupByGroup函数中,您必须编写如下代码

 groupByCategory = groupBy(groupByGroup[0], function(item)
  {
    return [item.category,item.group];
  })

and remove if(o.group=="x") from groupBy function. This problem can be solved easily using underscore.js.For help see this question

并从groupBy函数中删除if(o.group= "x")。这个问题可以用underscore.js轻松解决。为了帮助大家理解这个问题

Underscore.js: Sum of items in a collection

下划线。js:集合中项目的总和

Hope this will help you.

希望这对你有帮助。

#1


6  

The following code works for me. Query Northwind Order_Details service for a couple of Products via a generic binding, map reduce the the returned bindings and aggregate the Quantity of each order to the total Quanity sold, show the results in a column chart.

下面的代码对我有用。查询Northwind Order_Details服务通过一个通用绑定,映射减少返回的绑定,并将每个订单的数量汇总到所销售的全部数量,并在列图表中显示结果。

see jsBin Example

看到jsBin例子

note sap.viz introduces Array.prototype.map and Array.prototype.reduce functions

注意sap.viz介绍Array.prototype。地图和Array.prototype。减少功能

var sURI = 'http://services.odata.org/Northwind/Northwind.svc/';
var oDataModel = new sap.ui.model.odata.ODataModel(sURI, true);
oDataModel.setSizeLimit(10000);
var oJSONModel = new sap.ui.model.json.JSONModel({}, 'jmodel');

// handle list of contexts
var handler = function(oEvent) {
    var mapCallback = function(oContext) {
        var obj = {};
        obj.ProductID = oContext.getObject().ProductID,
        obj.Quantity = oContext.getObject().Quantity
        return obj;
    };

    var reduceCallback = function(aPrev, oCurr) {
        var aNext = aPrev;
        var bFound = false;

        aNext.forEach(function(item) {
            if (item.ProductID === oCurr.ProductID) {
                bFound = true;
                item.Quantity += oCurr.Quantity;
            }
        })

        if (bFound === false) {
            aNext.push(oCurr);
        }

        return aNext;
    };
    //release handler
    oBindings.detachChange(handler);

    var aTotals = oEvent.oSource.getContexts().map(mapCallback).reduce(reduceCallback, []);
    oJSONModel.setData({
        'Order_Totals': aTotals
    });
};

// Filter all orders by 3 products
var oFilter1 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '1');
var oFilter2 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '68');
var oFilter3 = new sap.ui.model.Filter("ProductID", sap.ui.model.FilterOperator.EQ, '11');
var aFilter = [oFilter1, oFilter2, oFilter3];

// Sort by ProductID
var oSorter = new sap.ui.model.Sorter("ProductID", false, true);

// Reduce the returned payload by nominating need fields
var oSelect = {
    select: 'ProductID,Quantity'
}

var oBindings = oDataModel.bindList("/Order_Details", null, oSorter, aFilter, oSelect);

// call OData service and handle results
oBindings.attachChange(handler);
oBindings.getContexts();

var oDataset = new sap.viz.ui5.data.FlattenedDataset({
    dimensions: [{
        axis: 1,
        name: 'ProductID',
        value: "{ProductID}"
    }],
    measures: [{
        name: 'Quantity Sold',
        value: '{Quantity}'
    }],
    data: {
        path: "/Order_Totals"
    }
});

var oColumnChart = new sap.viz.ui5.Column({
    width: "80%",
    height: "400px",
    plotArea: {
        'colorPalette': d3.scale.category20().range()
    },
    title: {
        visible: true,
        text: 'Qutantity Sold by Product'
    },
    dataset: oDataset
});

oColumnChart.setModel(oJSONModel);

#2


1  

For your final result i have written a code. Although it is not fully optimized but it works fine.

对于你的最终结果,我写了一段代码。虽然它不是完全优化的,但是它工作得很好。

Here is your full code

这是您的全部代码

var data = [
 {"category" : "A", "value" : 1, "group" : "x"},
 {"category" : "B", "value" : 2, "group" : "y"},
 {"category" : "C", "value" : 3, "group" : "x"},
 {"category" : "A", "value" : 4, "group" : "y"},
 {"category" : "A", "value" : 5, "group" : "x"}
];

function groupBy( array , f )
{
  var groups = {};
  array.forEach( function( o )
  {
    if(o.group=="x")
    {
        var group = JSON.stringify( f(o) );
        groups[group] = groups[group] || [];
        groups[group].push( o );
    }

  });
  return Object.keys(groups).map( function( group )
  {
    return groups[group]; 
  })
}
var groupByGroup = groupBy(data, function(item)
{
  return [item.group];
});
var groupByCategory = groupBy(groupByGroup[0], function(item)
{
  return [item.category];
});
getData(groupByCategory);

function getData(groupByCategory)
{
  var  finalData=[];
    for(var i=0;i< groupByCategory.length;i++)
    {
    var temp=0;
        for(var j=0;j<groupByCategory[i].length;j++)
        {
            temp+=parseInt(groupByCategory[i][j].value);
        }
        finalData.push({"category":groupByCategory[i][0].category, "value":temp})
    }
    console.log(finalData);//final data is your required results
}

If you want to compare using two parameter .Suppose you want to compare by category as well as group then in groupByGroup function you have to write as follow

如果您想使用两个参数进行比较,假设您想要按类别和组进行比较,那么在groupByGroup函数中,您必须编写如下代码

 groupByCategory = groupBy(groupByGroup[0], function(item)
  {
    return [item.category,item.group];
  })

and remove if(o.group=="x") from groupBy function. This problem can be solved easily using underscore.js.For help see this question

并从groupBy函数中删除if(o.group= "x")。这个问题可以用underscore.js轻松解决。为了帮助大家理解这个问题

Underscore.js: Sum of items in a collection

下划线。js:集合中项目的总和

Hope this will help you.

希望这对你有帮助。