• Saiku嵌入系统使用时传参数访问saiku(十六)


    Saiku嵌入系统使用时传参数访问saiku

    Saiku通过iframe嵌入其他系统使用时,我们可以设定参数信息,然后根据url中参数对结果进行筛选哦。

    这里我们实现的是根据日期字段进行范围查询,URL请求中需要多加如下两个参数  startdate , enddate ,也就是开始日期与结束日期。

     

    实现日期的范围查询 saiku  date range,主要有以下步骤

    1. 修改源代码 saiku-ui 项目下的 jssaikumodelsQuery.js(如果你不是本地编译的源码也可以直接修改 saiku-server omcatwebappsROOTjssaikumodels 目录下的 Query.js )

    在Query.js下的 run方法中增加如下代码段:

    //根據用戶輸入的開始日期與結束日期查詢範圍數據
    var dimensionArr = exModel.queryModel.axes.ROWS.hierarchies; //取出行信息中的所有维度信息 dimension,用一个数组接收
      for(var i=0;i<dimensionArr.length;i++){
    	//判断维度信息中是否有countdate这个时间维度(这是固定的)
    	if(dimensionArr[i]!=null && dimensionArr[i].dimension == "countdate" ){
    		var paramsURI = Saiku.URLParams.paramsURI(); //得到URl中传过来的参数信息
    		//判断参数是否为空
    		if(paramsURI.startdate != null && paramsURI.startdate != undefined && paramsURI.startdate != ""&&
    			paramsURI.enddate != null && paramsURI.enddate != undefined && paramsURI.enddate != ""){
    			var startdate=paramsURI.startdate; //获取开始日期
    			var enddate=paramsURI.enddate; //获取结束日期
    			//更改level下的mdx表达式,将日期范围的筛选信息添加到mdx表达式中
    			dimensionArr[i].levels.countdate.mdx="[countdate].[countdate].[countdate].["+startdate+"]:[countdate].[countdate].[countdate].["+enddate+"]";
    					
    		}
    	}
    }
    

     这里最主要的是就是找到需要改动的位置了:(文末提供了修改后完整的Query.js文件)

    exModel.queryModel.axes.ROWS.hierarchies 这个数组中找到countdate ,然后再修改countdate对应 levels.coundate下的mdx值

    层级关系如下图:(0是可变的哟,可能是下标1,2,3..... 所以上面代码中用到了 for循环去找 countdate )

    2. saiku中xml文件中的cube中必须配置日期字段,我用的是countdate字段,配置如下

       <Dimension name="countdate" foreignKey="ID" >
                <Hierarchy  hasAll="true"  primaryKey="ID" allMemberName="countdate" >
    		 <Level name="countdate" table="aaa" column="countdate" type='Date'  uniqueMembers="false" /> <!--这里的 column=countdate ,countdate为数据库的表中的日期字段名,可根据自己的表灵活变动啦-->
                </Hierarchy>
            </Dimension>
    

     

    3.Saiku配置数据信息的时候需要将日期字段拖到  数据框

    4.使用url发请求访问saiku中需带入startdate,enddate参数 (如果不带入这两个参数的话就不会进行范围筛选啦!!!然后就会正常查询全量数据)

    模板URL如下:

      http://10.99.77.78:8080/?username=admin&password=aaa&startdate=2019-03-06%2000:00:00.0&enddate=2019-03-10%2000:00:00.0&plugin=false&mode=view#query/open//KPI/aa.saiku

    URL解析

      http://10.99.77.78:8080/    #是我的saiku的访问地址

      username=admin&password=aaa   #分别是我登录saiku的用户名以及密码

      startdate=2019-03-06%2000:00:00.0&enddate=2019-03-10%2000:00:00.0    #是我设定的开始时间以及结束时间,我想查询countdate值为3.6到3.10的数据。这里需要说明一下我的countdate中有2019-03-06 00:00:00.0 ,2019-03-10 00:00:00.0  这两个值哦。

      plugin=false&mode=view#query/open/    #这里指不以插件的方式嵌入,嵌入的模式为view(会带出导出excel那一排工具栏信息)

      /KPI/aa.saiku   #这个就是我保存的数据信息啦,我自己新建了个KPI目录,然后保存的数据命名为 aa .

    5.过滤结果如下图:

    解析:( 其实上面添加的注释已经比较详细的,嘻嘻  ,需要注意的主要有以下4点)

    1. 数据库中必须有一个countdate日期字段(名字当然可以随意)

    2.Schema文件中 对应的cube信息中必须配置 countdate字段如下:(关键的是  Dimension下的name  Hierarchy下的allMemerName  Level下的name 命名都为countdate )

        <Dimension name="countdate" foreignKey="ID" >
                <Hierarchy  hasAll="true"  primaryKey="ID" allMemberName="countdate" >
    		<Level name="countdate" table="aaa" column="countdate" type='Date'  uniqueMembers="false" /> <!--这里的 column=countdate ,countdate为数据库的表中的日期字段名,可根据自己的表更改-->
                </Hierarchy>
            </Dimension>
    

    3.如果需要根据日期进行范围筛选,url中必须添加参数 startdate,enddate 哦

    4.想要获取正确的筛选结果,startdate以及enddate的值必须是当前cube中已有的值!!!(不然就会报错啦,就像你在saiku中使用参数一样,参数值一定要填写当前结果中已有的值,关于日期就很较真啦,时分秒都要对应上才行哦)  

    >>>更改后的Query.js文件

    这里再提供一下修改之后的完整Query.js ,其它地方都没有改动,就只是添加了上方内容,详情如下

    Query.js

    /*
     *   Copyright 2012 OSBI Ltd
     *
     *   Licensed under the Apache License, Version 2.0 (the "License");
     *   you may not use this file except in compliance with the License.
     *   You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *   Unless required by applicable law or agreed to in writing, software
     *   distributed under the License is distributed on an "AS IS" BASIS,
     *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *   See the License for the specific language governing permissions and
     *   limitations under the License.
     */
    
    /**
     * Workspace query
     */
    var Query = Backbone.Model.extend({
    
        formatter: Settings.CELLSET_FORMATTER,
        properties: null,
    
        initialize: function(args, options) {
            // Save cube
            _.extend(this, options);
    
            // Bind `this`
            _.bindAll(this, "run");
    
            // Generate a unique query id
            this.uuid = 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
                function (c) {
                    var r = Math.random() * 16 | 0,
                    v = c == 'x' ? r : (r & 0x3 | 0x8);
                    return v.toString(16);
                }).toUpperCase();
    
            this.model = _.extend({ name: this.uuid }, SaikuOlapQueryTemplate);
            if (args.cube) {
                this.model.cube = args.cube;
            }
            this.helper = new SaikuOlapQueryHelper(this);
    
            // Initialize properties, action handler, and result handler
            this.action = new QueryAction({}, { query: this });
            this.result = new Result({ limit: Settings.RESULT_LIMIT }, { query: this });
            this.scenario = new QueryScenario({}, { query: this });
    
            // A flag to tell who changed selection members
            this.updatedSelectionFromModal = false;
        },
    
        parse: function(response) {
            // Assign id so Backbone knows to PUT instead of POST
            this.id = this.uuid;
            if (response.name) {
                this.id = response.name;
                this.uuid = response.name;
            }
            this.model = _.extend(this.model, response);
            this.model.properties = _.extend({}, Settings.QUERY_PROPERTIES, this.model.properties);
        },
    
        setProperty: function(key, value) {
                this.model.properties[key] = value;
        },
    
        getProperty: function(key) {
            return this.model.properties[key];
        },
    
        syncSelectionsModalAndUpdateParameters: function() {
            if (this.updatedSelectionFromModal) {
                var mParameters = this.helper.model().parameters;
                for (var mKey in mParameters) {
                    var mVal       = mParameters[mKey];
                    var selections = this.helper.getSelectionsForParameter(mKey);
    
                    mVal = selections.map(function(sel) { return sel.caption; }).join();
                    mParameters[mKey] = mVal;
                }
            } else {
                var mParameters = this.helper.model().parameters;
                for (var mKey in mParameters) {
                    var mVal       = mParameters[mKey];
                    var mLevel     = this.helper.getLevelForParameter(mKey);
                    var selections = this.helper.getSelectionsForParameter(mKey);
    
                    if (mVal !== null && mVal !== undefined) {
                        this.helper.setSelectionsForParameter(mKey, _.filter(selections, function(sel) {
                            var containsParam = false;
                            _.each(mVal.split(','), function (v) {
                                if (sel.caption === v) {
                                    containsParam = true;
                                    return false;
                                }
                            });
                            return containsParam;
                        }));
                    }
                }
            }
    
            this.updatedSelectionFromModal = false;
        },
    
        run: function(force, mdx) {
            this.syncSelectionsModalAndUpdateParameters();
    
            var self = this;
            // Check for automatic execution
            Saiku.ui.unblock();
            if (typeof this.model.properties != "undefined" && this.model.properties['saiku.olap.query.automatic_execution'] === false &&
    			(force === false || force === undefined || force === null)) {
                return;
            }
            this.workspace.unblock();
    
            $(this.workspace.el).find(".workspace_results_info").empty();
            this.workspace.trigger('query:run');
            this.result.result = null;
            var validated = false;
            var errorMessage = '<span class="i18n">Query Validation failed!</span>';
    
            var exModel = this.helper.model();
    		for(var k in this.attributes) {
    			var att = this.attributes[k];
    			if(k.substring(0,5)==="PARAM"){
    				var p = k.substring(5, k.length);
    				exModel.parameters[p] = att;
    			}
    
    		}
            if (exModel.queryType == "OLAP") {
                if (exModel.type == "QUERYMODEL") {
                    var columnsOk = Object.keys(exModel.queryModel.axes.COLUMNS.hierarchies).length > 0;
                    var rowsOk = Object.keys(exModel.queryModel.axes.ROWS.hierarchies).length > 0;
                    var detailsOk = exModel.queryModel.details.axis == 'COLUMNS' && exModel.queryModel.details.measures.length > 0;
                    if (!rowsOk || !columnsOk || !detailsOk) {
                        errorMessage = "";
                    }
                    if (!columnsOk && !detailsOk) {
                        errorMessage += '<span class="i18n">You need to include at least one measure or a level on columns for a valid query.</span>';
                    }
                    if(!rowsOk) {
                        errorMessage += '<span class="i18n">You need to include at least one level on rows for a valid query.</span>';
    
                    }
                    if ( (columnsOk || detailsOk) && rowsOk) {
                        validated = true;
                    }
    
                } else if (exModel.type == "MDX") {
                    validated = (exModel.mdx && exModel.mdx.length > 0);
                    if (!validated) {
                        errorMessage = '<span class="i18n">You need to enter some MDX statement to execute.</span>';
                    }
                }
            }
            if (!validated) {
                this.workspace.table.clearOut();
                $(this.workspace.processing).html(errorMessage).show();
                this.workspace.adjust();
                Saiku.i18n.translate();
                return;
            }
    
    
            // Run it
            this.workspace.table.clearOut();
            $(this.workspace.processing).html('<span class="processing_image">  </span> <span class="i18n">Running query...</span> [ <a class="cancel i18n" href="#cancel">Cancel</a> ]').show();
            this.workspace.adjust();
            this.workspace.trigger('query:fetch');
    		Saiku.i18n.translate();
            var message = '<span class="processing_image">  </span> <span class="i18n">Running query...</span> [ <a class="cancel i18n" href="#cancel">Cancel</a> ]';
            this.workspace.block(message);
    /*
            TODO: i wonder if we should clean up the model (name and captions etc.)
            delete this.model.queryModel.axes['FILTER'].name;
    */
      
    		
    	//根據用戶輸入的開始日期與結束日期查詢範圍數據
    	var dimensionArr = exModel.queryModel.axes.ROWS.hierarchies; //取出行信息中的所有维度信息 dimension,用一个数组接收
    	for(var i=0;i<dimensionArr.length;i++){
    		//判断维度信息中是否有countdate这个时间维度(这是固定的)
    		if(dimensionArr[i]!=null && dimensionArr[i].dimension == "countdate" ){
    			var paramsURI = Saiku.URLParams.paramsURI(); //get the param from url
    			//判断参数是否为空
    			if(paramsURI.startdate != null && paramsURI.startdate != undefined && paramsURI.startdate != ""&&
    				paramsURI.enddate != null && paramsURI.enddate != undefined && paramsURI.enddate != ""){
    				var startdate=paramsURI.startdate;
    				var enddate=paramsURI.enddate;
    				//更改level下的mdx表达式
    				dimensionArr[i].levels.countdate.mdx="[countdate].[countdate].[countdate].["+startdate+"]:[countdate].[countdate].[countdate].["+enddate+"]";
    					
    			}
    		}
    	}
    
            this.result.save({},{ contentType: "application/json", data: JSON.stringify(exModel), error: function() {
                Saiku.ui.unblock();
                var errorMessage = '<span class="i18n">Error executing query. Please check the server logs or contact your administrator!</span>';
                self.workspace.table.clearOut();
                $(self.workspace.processing).html(errorMessage).show();
                self.workspace.adjust();
                Saiku.i18n.translate();
            } });
        },
    
        enrich: function() {
            var self = this;
            this.workspace.query.action.post("/../enrich", {
                contentType: "application/json",
                data: JSON.stringify(self.model),
                async: false,
                success: function(response, model) {
                    self.model = model;
                }
            });
        },
    
        url: function() {
            return "api/query/" + encodeURI(this.uuid);
        }
    });
    

     

  • 相关阅读:
    LoadRunner支持的IE版本
    构建10亿级PV的大型网站设计要点 网络层
    珠海金山软件急聘性能测试工程师【内部推荐】
    PrefTest性能测试解决方案 C/S结构应用系统的压力测试
    Android性能测试主要方法
    使用LoadRunner监控Apach服务器的步骤
    MySQL+HandlerSocket
    Android configChanges属性
    创业故事:腾讯的创始人们
    [置顶] 学习linux的几点忠告
  • 原文地址:https://www.cnblogs.com/DFX339/p/10560180.html
Copyright © 2020-2023  润新知