| 免费下载:IBM® Cognos® Express V9.5 或者 Cognos® 8 Business Intelligence Developer Edition V8.4 试用版 |
|---|
| 下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。 |
数据挖掘,就是对已有的数据运用统计学的算法,去除杂点数据,分析出数据中潜在的规律;而 Cognos 则主要是对已有的数据进行简单的建模后, 以各种样式的图形报表展示给企业的决策者,使得决策者根据基于历史数据展示的图形报表快速的做出决策;前者是对已有数据进行数据挖掘,后者是对已有数据的报表展示, 如果能够在向决策者展示报表之前对数据进行数据挖掘处理,则是非常有意义的,能够帮助决策者做出更加准确的决策。 Modeler 是 IMB SPSS 公司开发的一个数据挖掘软件,本文将以 Modeler 为例,来阐述如何实现 Modeler 跟 Cognos 的集成。
图 1. 实现该集成的整体架构
在上图中,有四个模块:最上层的是 Modeler Server 层,是基于 c++ 语言实现的可运行于各个平台的一个服务程序,功能是对已有数据进行 数据挖掘运算;第四层是 Cognos Server;为了实现 Modeler 跟 Cognos 的集成,我们增加了 2 个模块,就是上图中的第二层和第三层,第三层是 一个由 Java 实现的 jar 包,通过与 Cognos Server 交互来实现此次集成所需要的所有与 Cognos Server 相关的功能;第二层则是由 c++ 语言 实现的一个动态库,通过 JNI 来调用第三层中实现的接口,供 Modeler Server 使用。可以看出,第二层和第三层就是连接 Modeler Server 跟 Cognos Server 交互的一个桥梁,通过第二层和第三层,Modeler Server 可以从 Cognos Server 中获得企业中已有的历史数据,然后对这些 数据进行数据挖掘处理,最后存储到 Cognos Server 中,Cognos Server 根据处理过的数据来生成报表,展示给企业的决策者,供其作出更加 准确的决策。
根据上面的描述,要实现 Modeler 跟 Cognos 的集成,我们只需要实现中间两层,即 CognosModule 跟 CognosDataManager。 第二层是简单的 JNI 调用 Java 接口的封装,在此不作深入介绍,本文将着重介绍第三层 CognosDataManager 的实现。
整个集成过程就是从 Cognos 中导出数据,供 Modeler 做数据挖掘处理,然后再将 Modeler 处理过的数据以 Package 的形式 publish 到 Cognos 中去, Cognos 可以基于此 Package 来生成报表,供决策者做出决策。所以整个集成过程分为两个阶段:第一阶段是从 Cognos 向 Modeler 导入数据 (import data),第二阶段是从 Modeler 向 Cognos 导出数据(export data)。
通过上面阐述,我们可以看出整个集成的过程实际上就是通过跟 Cognos Server 的交互,从 Cognos Server 中取出数据和向 Cognos Server 中写入数据的过程。要实现跟 Cognos Server 交互,我们需要使用 Cognos 提供的一组 jar 包,通过这些 Jar 包提 供的接口,我们可以轻松的跟 Cognos Server 交互。这些 jar 包可以从 Cognos 发布的 SDK 安装包中获得。所有用到的 Jar 包如下:
- activation.jar
- axis.jar
- axisCognosClient.jar
- commons-discovery.jar
- commons-logging.jar
- dom4j.jar
- jaxen.jar
- jaxrpc.jar
- mail.jar
- saaj.jar
- wsdl4j-1.5.1.jar
- xercesImpl.jar
- xml-apis.jar
还有一个第三方 jar 包 castor-1.2.jar 在集成中也要用到。
这些 jar 包中,axisCognosClient.jar 提供了我们跟 Cognos Server 交互的所有接口,它依赖于其他所有的 jar 包。
Cognos Server 是以 Web Service 的方式向外提供服务,当我们调用 axisCognosClient.jar 中的接口跟 Cognos Server 通信时, 该 Jar 包负责将我们的输入转化成相应的 Web Service 请求发送给 Service, 然后将 Service 返回的应答在返回给我们,这样就完成了一次通信。
下面我们将分别阐述如何实现从 Cognos 向 Modeler 导入数据和从 Modeler 向 Cognos 导出数据。
在讨论集成之前,我们需要先了解以下 Cognos 中的几个概念:
- Package:是 Cognos 中一个重要的概念,它是一个抽象的数据集对象,一个 Package 可以映射到一个数据库中的多个表上,用户可以通过 Package 获得这些数据库表中的数据。
- Report:前面我们提到,一个公司的决策者总是希望看到自己所关注的某些历史数据的图形式报表展示,这个报表就是我们这里要说的 Report,Report 是基于 Package 设计 出来的,他包含了 Package 中所有或者部分数据映射(也就是决策者所关注的数据)
- Report Specification:在 Cognos 中,每个 Report 对象都是以 XML 形式描述的,称之为 Report Specification。包含了两部分信息,一部分是 Query, 包含了该 Report 所映射到的在数据库中表和列的数据信息,通过这一部分,可以从数据库中查询出数据;另一部分是 Layout,用于对查询出的数据进行展示, 比如以饼状图、柱状图、表状等方式展示。
图 2. 使用浏览器访问 Cognos Server
点击”IBM Cognos content”,进去后点击 Launch 下拉菜单,选择 Report Studio 菜单项来运行 Report Studio,如下图 :
图 3. 运行 Report Studio
通过选择创建 Report 所依赖的 Package 后,选择”Create New”来基于此 Package 来创建一个新的 Report,如下图:
图 4. 创建一个 List 样式的 Report
上图中,我们选择的是名为 TEST 的 pakcage,上图显示了 Cognos 所支持的 Report 的所有样式,这里我们选择 List 样式,来创建一个 List Report,如下图:
图 5. Package 的结构
在上图左侧中,显示的是我们所选择的名为 TEST 的 package 的结构,最顶层的 TEST 表示 Package 名,第二层的 TEST 表示该 Package 下包含了一个名叫 TEST 的数据库表,称之为 Query Susbject( 当然一个 package 中可以包含多个数据库表的映射 ),TEST 下面的所有条目称之为 QueryItem,表示该表 中的所有列。然后我们将 TEST 表中的所有列选择到右边,这样就创建了一个包含数据库表 TEST 中所有列的一个 Report,运行该 Report 如下图:
图 6. 运行 Report
因为之前我们选择 Report 的样式为 List 样式,所以运行结果将以列表形式显示该 Report 包含的所有列的所有数据,如下图:
图 7. Report 的运行结果
点击图 5 中工具栏上的 XML 图标,可以查看该 Report 的 Report Specification,如下图(我将它拷贝到了 oXygen 工具中进行查看)。
图 8. Report Specification 示例
在上图中,有五个红圈标注:第一个标注是 modelPath,表示的是该 Report 是基于哪个 Package 创建的;第二个标注是 Queries, 表示这部分是要从数据库中获取数据;第三个标注是 dateItem,表示的是数据库中的一列,根据它的 expression 属性可以看出他是 哪个数据库中的哪一列,比如 [CognosTest].[TEST].[Age],其中 CognosTest 是我们在 Cognos 中配置的 Data Source,表示一个数据 库连接,包含了数据库所在机器,数据库名,连接数据库的用户名密码等信息,这里只是通过引用该 Data Source 来访问数据库,TEST 表示 名为 TEST 的数据库表,Age 表示名为 Age 的数据库表中的列;第四个标注是 layouts,表示这些数据是以什么样的形式来展示给用户,第五个 标注是 List,表示这个 Report 将这些数据以一个 List 的方式展示给用户的。 Cognos 支持多种展示形式,包括自定义模板展示,如下图:
图 9. Cognos 数据展示格式
从 Cognos 向 Modeler 导入数据,让 Modeler 对之进行数据挖掘和数据分析,需要实现以下几个部分的功能:
- 连接 Cognos Server
- 获得 Cognos Server 中所有的 Package
- 获得用户选择的 Package 的 MetaData
- 根据用户选择的 QueryItem,获得它们的存储类型,并且根据这些 QueryItem 来生成一个表状的 Report,通过 Report Service 提供的接口来 Render 此 List Report,从而得到一个二维表状数据。读取这些数据,供 Modeler 进行数据挖掘处理。
下面我们分别介绍这几部分的实现:
1) 连接 Cognos Server:
可以采用匿名或者指定的 credentials 来连接。如下图 :
图 10. 连接 Cognos Server
在 Modeler 中,通过该 UI 获得用户连接 Cognos Server 的信息,这些信息包含了 2 部分内容,一部分是 Cognos Server 的 URL,用来 连接 Cognos Server,另一部分是 credentials,用来 LogonCognos Server,这些信息通过 Modeler Server 传递个图一中的第三层: CognosDataManger 层。所以该部分的实现包括两步:连接 Cognos Server 和 Logon Cognos Server. Cognos Server 是有 10 多个 Service 服务程序组成,每个 Service 服务负责不同的功能,在这个集成中,我们只使用到其中三种 Service 服 务,所以在连接是,我们只需要得到该三种 Service 服务:ContentManagerService、ReportService、MetadataService。
清单 1. 连接 Cognos Server
public ContentManagerService_PortType connectToCognosServer(String CMURL)
{
// Create the service locators
cmServiceLocator = new ContentManagerService_ServiceLocator();
reportServiceLocator = new ReportService_ServiceLocator();
metadataServiceLocator = new MetadataService_ServiceLocator();
try
{
java.net.URL serverURL = new java.net.URL(CMURL);
//acquire references to services
cmService = cmServiceLocator.getcontentManagerService(serverURL);
repService = reportServiceLocator.getreportService(serverURL);
metadataService = metadataServiceLocator.getmetadataService(serverURL);
return cmService;
}
//handle uncaught exceptions
catch (MalformedURLException e)
{
System.out.println("Malformed URL:\n" + e.getMessage());
return null;
}
catch (ServiceException e)
{
System.out.println("Service Exception:\n" + e.getMessage());
return null;
}
}
|
清单 2. Logon Cognos Server
public void quickLogon(
CRNConnect connection,
String namespace,
String uid,
String pwd)
throws Exception
{
StringBuffer credentialXML = new StringBuffer();
credentialXML.append("<credential>");
credentialXML.append("<namespace>");
credentialXML.append(namespace);
credentialXML.append("</namespace>");
credentialXML.append("<username>");
credentialXML.append(uid);
credentialXML.append("</username>");
credentialXML.append("<password>");
credentialXML.append(pwd);
credentialXML.append("</password>");
credentialXML.append("</credential>");
String encodedCredentials = credentialXML.toString();
credentialString = encodedCredentials;
connection.getCMService().logon(new XmlEncodedXML(encodedCredentials),
new SearchPathSingleObject[] {});
}
|
2) 获得 Cognos Server 中所有的 Package:
在连接成功后,我们需要获得该 Cognos Server 中的所有 Package 给 Modeler,让用户选择某一个 Package 来进行数据导入, 如下图 ( 图中橘黄色的文件夹表示一个文件夹,蓝色的文件夹表示一个 Package。在 Cognos Content 中,文件夹中可以存放 Package, report 等对象,Package 中也可以存放 Package,Report 等对象 )。
图 11. 获得 Cognos Server 中所有 Package,显示给用户
我们可以通过 ContentManagerService 提供的 runQuery 接口来查询出所有的 package。
清单 3. 获得 Cognos Server 中所有的 Package
List<CognosPropEnum> props = new ArrayList<CognosPropEnum>();
props.add(CognosPropEnum.defaultName);
props.add(CognosPropEnum.searchPath);
String searchCondition = "CAMID(\"::Anonymous\")/folder[@name='My Folders']
//package | /content//package";
List<BaseClassWrapper> results =getCMService().runQuery(searchCondition, props);
|
将查找到的所有 Package 按照其目录结构组织成一个 XML 格式的字符串返回给 Modeler。Modeler 展示这些 Package 给用户,如上图所示。
3) 获得用户选择的 Package 的 MetaData:
当用户选择了某一个 Package 后,我们需要得到该 Package 的 MetaData,通过这些 Metadata 来导入数据,如下图所示:
图 12. 获得用户指定的 Package 的 Metadata
在上图中,如红圈所示,用户选择的是 My Folders 下面的名为 TEST 的 Package;Package content 部分显示 的就是得到的该 Package 的 MetaData,顶层的 TEST 表示 Package 名称;第二层的 CognosTest 是 Cognos Data Source, 表示一个数据库连接,他指定到一个特定的数据库上;第三层的 TEST 表示该数据库中的一个名为 TEST 的数据库表;Test 下 面的条目就是该表下的所有列。用户可以选择所有列或者你某些列到右边,根据所选列来导出数据。
该部分的实现是通过向 ReportService 发送 metadataRequest 请求来获取 Package 的 Metadata, 即调用 Report Service。
清单 4. 获取 Package 的 Metadata
String sModel = sPackageSearchPath;
String sXML =
"<metadataRequest connection=\""
+ sModel
+ "\">"
+ "<Metadata Depth='' "
+ "no_collections='1'>"
+ "<Properties>"
+ "<Property name='*/@name'/>"
+ "<Property name='*/@datatype'/>"
+ "<Property name='*/@_path'/>"
+ "<Property name='*/@_ref'/>"
+ "<Property name='*/@isNamespace'/>"
+ "<Property name='*/@usage'/>"
+ "<Property name='*/@namespace'/>"
+ "<Property name='*/@expression'/>"
+ "<Property name='*/@refobj'/>"
+ "<Property name='./folder'/>"
+ "<Property name='./querySubject'/>"
+ "<Property name='./queryItem'/>"
+ "<Property name='./queryItemFolder'/>"
+ "<Property name='./measure'/>"
+ "<Property name='./measureFolder'/>"
+ "<Property name='./dimension'/>"
+ "<Property name='./hierarchy'/>"
+ "<Property name='./rootCaption'/>"
+ "<Property name='./level'/>"
+ "<Property name='./filter'/>"
+ "<Property name='./calculation'/>"
+ "<Property name='./folder/*'/>"
+ "</Properties>"
+ "</Metadata>"
+ "</metadataRequest>";
try {
return connection.getReportServiceWrapper().renderMetaDataRequest(sXML);
}
catch (CognosException e){
CognosLogUtil.writeException(e);
return null;
}
|
在返回的 Medata 中包含了所有数据库表列的存储类型,如下图所示:
图 13. 从 Report Service 返回的 Package 的 Metadata
4) 根据用户选择的 QueryItem,生成一个 List Report,通过 Report Service 的 runSpecification 接口来 Render 此 List Report,从而得到一个二维表状数据:
图 14. 用户选择 QueryItem 进行数据导出
根据用户选择的 QueryItem 来产生 List Report:
要产成 Report,我们只需要生成它的 Report Specification 就可以,要生成 Report Specification, 必须根据 Report 的 schema 来生成,我们可以从 Cognos 的安装目录获得此文件(如:..\IBM\cognos\c10\schemas\rspec\7.0\ V5_report_one.xsd), 利用第三方库 castor 根据 schema 文件生成一批用来描述 report 的 java 源文件,用这些源文件中的对象来构造 Report 对象,最后将该 Report 对象 marshal 成一个 xml, 便得到了 Report Specification,在这次集成中,我们需要生成 List Report 以便得到二维表状数据,所以在生成 Report Specification 时要生成 List 样式的 Report。- 调用 ReportService 的 runSpecification 接口来运行此 List Report:
清单 5. 运行 Report Specification
Option runOptions[] = new Option[7];
int index = 0;
RunOptionBoolean saveOutput = new RunOptionBoolean();
saveOutput.setName(RunOptionEnum.saveOutput);
saveOutput.setValue(false);
runOptions[index] = saveOutput;
index++;
RunOptionStringArray outputFormat = new RunOptionStringArray();
outputFormat.setName(RunOptionEnum.outputFormat);
outputFormat.setValue(new String[]{"CSV"});
runOptions[index] = outputFormat;
index++;
RunOptionOutputEncapsulation outputEncapsulation =
new RunOptionOutputEncapsulation();
outputEncapsulation.setName(RunOptionEnum.outputEncapsulation);
outputEncapsulation.setValue(OutputEncapsulationEnum.none);
runOptions[index] = outputEncapsulation;
index++;
RunOptionData data = new RunOptionData();
data.setName(RunOptionEnum.data);
data.setValue(DataEnum.runWithAllData);
runOptions[index] = data;
index++;
RunOptionEncoding encoding = new RunOptionEncoding();
encoding.setName(RunOptionEnum.attachmentEncoding);
encoding.setValue(EncodingEnum.MIMECompressed);
runOptions[index] = encoding;
index++;
RunOptionLanguageArray outputLocale = new RunOptionLanguageArray();
outputLocale.setName(RunOptionEnum.outputLocale);
outputLocale.setValue(new String[]{Locale.getDefault().toString()});
runOptions[index] = outputLocale;
index++;
RunOptionBoolean prompt = new RunOptionBoolean();
prompt.setName(RunOptionEnum.prompt);
prompt.setValue(false);
runOptions[index] = prompt;
index++;
ParameterValue[] pv = new ParameterValue[] {};
Specification specification=new Specification(spec);
ReportServiceReportSpecification reportSpec =
new ReportServiceReportSpecification();
reportSpec.setValue(specification);
AsynchReply asynchReply = getReportService().
runSpecification(reportSpec, pv, runOptions);
while( (asynchReply.getStatus() != AsynchReplyStatusEnum.complete)
&&(asynchReply.getStatus()!=AsynchReplyStatusEnum.conversationComplete))
{
if (hasSecondaryRequest(asynchReply, "wait"))
{
asynchReply = getReportService().wait(
asynchReply.getPrimaryRequest(), new ParameterValue[] {},
new Option[] {});
}
}
|
清单 6. 获取运行 Report Specification 后的数据
Object[] attachments = ((Stub) getReportService()).getAttachments();
AttachmentPart pAttach = (AttachmentPart) attachments[0];
if (pAttach.getAttachmentFile() == null) {
// 数据在 pAttach 对象中(内存中)
}else{
// 因为数据量大,数据生成在了临时目录下的临时文件中,文件路径为
// pAttach.getAttachmentFile(), 通过读取该文件来读取数据
}
|
根据 pAttach 来读出数据,供 Modeler 进行数据挖掘和数据处理,至此,我们便完成了从 Cognos 中导出数据的所有实现,下图显示了导出的数据结果:
图 15. 从 Cognos 向 Modeler 导入的数据:
3. 把 Modeler 处理后的数据导入到 Cognos 中
在 Modeler 对数据进行数据挖掘处理后,我们需要将数据导入到 Cognos 中去,用这些处理后的数据生成 Report,使得决策者做出更加准确的决策。 把数据导入到 Cognos 中,分为以下两步来实现:
1) 在 Cognos Server 所连接的数据库中创建一个新表并将数据写入其中:(这一步是基本数据库操作,不再做详细描述)。
2) 基于此表创建一个 package 并且 publish 到 Cognos 中: 根据数据库及表的信息,创建一个 ActionScript,里边包含了基于此表产生 package 并且 publish 该 package 到 Cognos Content 指定目录下的所有 Actions,然后调用 MetadataService 的 接口 updateMetadata 来执行这些 Action,从而实现了产生 package 并将之 publish 到 Cognos 中指定目录下的目的。
通过本文,您已经对数据挖掘与 Cognos 的集成有所了解,并且可以通过 Modeler 体会如何快速的将 Cognos 中的数据 导入到 Modeler 中进行数据挖掘处理后,再将处理后的数据导入到 Cognos 中去。
学习
- 访问
“developerWorks Information Management 专区”
在这里可以学到更多关于信息管理相关的技术文档及教程等。
- 访问 Information Management 专区
访问 Information Management 专区了解更多有关 Cognos BI 专题的产品和技术资源。
- 访问
商业智能入门以及 Cognos 产品介绍
,了解 商业智能的基本概念和相关技术,并介绍了 Cognos 商业智能相关的产品。
- 访问
IBM Cognos 8 Business Intelligence,学习 IBM Cognos 8 Business Intelligence 产品的相关知识。
- 访问
Cognos更多地了解关于 IBM Cognos 的信息。
- 随时关注最新的
developerWorks 技术活动 和 网络广播。
获得产品和技术
-
选择最适合您的方式获得试用版 IBM 产品评估试用版软件:下载试用版产品、在线试用产品、在云环境中使用产品,或者花一些时间在
IBM SOA 人员沙箱 中学习如何高效地实现面向服务的架构。
- 利用
IBM 产品评估试用版软件 构建您的下一个开发项目,可直接通过 developerWorks 下载这些试用软件。
讨论
- 参与论坛讨论。
- 访问
developerWorks 博客,加入 developerWorks 中文社区,developerWorks 社区是一个面向全球 IT 专业人员,可以提供博客、书签、wiki、群组、联系、共享和协作等社区功能的专业社交网络社区。


