datacleaner第九部分

来源:互联网 发布:北京编程培训机构排名 编辑:程序博客网 时间:2024/04/27 14:37

第九部分。开发人员指南

表的内容

23。体系结构
数据访问
处理框架
24。通过代码执行的工作
概述的步骤和选项
步骤1:配置
步骤2:工作
步骤3:执行
步骤4:结果
25。开发人员资源
扩展开发教程
建筑DataCleaner
26岁。扩展包装
带注释的组件
单一JAR文件
扩展元数据的XML
组件的图标
27。嵌入DataCleaner

23章。体系结构

文摘

DataCleaner的体系结构可以从不同角度描述根据感兴趣的话题。在以下部分中,我们将介绍DataCleaner架构的不同方面。

表的内容

数据访问
处理框架

数据访问

在DataCleaner所有来源的数据称为“数据存储”。这个概念涵盖了在本地读/解析的来源,和那些“连接到”,如。数据库和应用程序。还可以写一些数据存储,例如关系数据库。

DataCleaner使用Apache元模型框架对数据的访问。从DataCleaner的角度来看,Apache元模型提供了大量的特性:

  1. 共同的相互作用不同的数据存储方式。

  2. 程序化的查询语法,特定于数据库的SQL方言进行了抽象,因此,也可用面向非SQL的数据存储(文件等)。

  3. 开箱即用的连接到很多资源,例如。CSV文件、关系型数据库、Excel电子表格和更多。

  4. 造型新来源的框架使用相同的常见模式。

DataCleaners数据存储模型也是可扩展的方式,你可以自己实现新的数据存储以连接DataCleaner遗留系统、应用程序接口等等。有关更多信息,请参阅开发人员资源一章。

处理框架

DataCleaner过程数据的方式略有不同而最相似(etl式)工具。首先在多线程的方式应用,其次在DataCleaner有时优化图的方式执行时间。

多线程:在DataCleaner多线程策略使工具有最少的阻挡和缓冲和并行性和潜在的最大数量分布。大多数etl式工具应用线程策略,每个组件的工作有自己的线程管理以及一个输入和一个输出缓冲区。DataCleaner线程管理是这样的,每个记录是并行处理——每个工作单元正在通过一个完整的工作图。这有很���有趣的特征:

  1. 有一个高度的自动“负载均衡”的组件——更少约束和瓶颈在最慢的组件的工作。

  2. 系统本身高度分布式处理因为有状态性是例外而不是规则。

  3. 有更少的浪费中间的缓冲组件的形式工作。

  4. 这种方法的一个缺点是,无法保证加工的顺序记录。这只是很少需要域的数据剖析和分析,如果是需要有技术应用解决方案。

图优化:虽然工作图(见将组件结合在一起)可能显示一个特定的顺序后,发动机在运行时可能做一些优化。一些组件可以提供优化策略包括改变源查询,这样的数量(或内容)改变处理记录。显然这是一个使用组件,只会被应用的副作用的情况下不影响其他组件的工作。原则有时也被称为“压低优化”。

这是一个“Null检查”的一个例子过滤器:如果一个Null检查应用于源列和所有其他组件需要Null或NOT_NULL结果(显式或隐式),那么“Null检查”过滤器可能添加一个源查询谓词过滤掉所有不相关的记录。在这一原则的更多信息,请阅读博客条目的在DataCleaner压低查询优化Kasper Sørensen”。

24章。通过代码执行的工作

文摘

在这一章里,我们将经历的一个最常见的用例将DataCleaner集成到您自己的应用程序,执行一个DataCleaner通过代码的工作。

表的内容

概述的步骤和选项
步骤1:配置
步骤2:工作
步骤3:执行
步骤4:结果

概述的步骤和选项

这个故事有两个变种——你想要什么样的配置选项?你想建立工作程序,作为.analysis或磁盘上的某个地方。xml文件吗?你会做任何处理的结果,还是工作本身包含所有必要的逻辑。

各个步骤和选项如下图中描述。在下面几节中我们将通过每个4步骤/列图:

步骤1:配置

DataCleaner班上表示的配置 DataCleanerConfiguration(以前“AnalyzerBeansConfiguration”)。你最需要DataCleanerConfiguration作为先决条件的操作。

最简单和最方便的选择获取DataCleanerConfiguration实例从文件加载它,通常叫conf.xml(参见配置文件为更多的细节在这章文件格式)。加载文件,使用JaxbConfigurationReader类,像这样:

InputStream inputStream = new FileInputStream("conf.xml"); JaxbConfigurationReader configurationReader = new JaxbConfigurationReader(); DataCleanerConfiguration configuration = configurationReader.read(inputStream);

或者,您可以通过编程方式构建配置,通过代码。这通常是更多的麻烦,但在某些情况下也很有用,如果配置构建动态之类的。

这里有一个例子,我们配置DataCleaner 2示例数据存储和threadpool 10个线程:

Datastore datastore1 = new CsvDatastore("my CSV file", "some_data.csv"); boolean multipleConnections = true Datastore datastore2 = new JdbcDatastore("my database", "jdbc:vendor://localhost/database", "com.database.Driver", "username", "password", multipleConnections); DataCleanerConfigurationImpl configuration = new DataCleanerConfigurationImpl(); configuration = configuration.replace(new MultiThreadedTaskRunner(10)); configuration = configuration.replace(new DatastoreCatalogImpl(datastore1, datastore2));

不管怎样,我们现在有了一个 DataCleanerConfiguration变量名的“配置”。然后我们可以继续定义工作运行。

步骤2:工作

像配置,我们可以选择从文件加载作业我们要运行,或通过编程方式构建它。

我们先来简单地从文件加载工作。我们需要使用JaxbJobReader类:

InputStream inputStream = new FileInputStream("my_job.analysis.xml"); JaxbJobReader jobReader = new JaxbJobReader(configuration); AnalysisJob analysisJob = jobReader.read(inputStream);

请注意,这是“香草”的情况。您还可以使用JaxbJobReader读元数据对一项工作,甚至阅读一份工作作为一个模板,这使得它可以实例化的工作一定的替代品。例如在DataCleaner如何使用此功能的桌面应用程序,看到模板工作部分。

生产工作的其他方式是建立以编程方式。这是很复杂的过程,很多不同取决于你想要什么样的工作。但API的设计使它尽可能容易。

给API的概述,考虑这个重要的类列表:

  1. AnalysisJobBuilder:表示一个可变正在建造的工作。这个生成器对象包含源列的工作,和所有的组件使用源列(或有时改变列)。

  2. TransformerComponentBuilder , FilterComponentBuilder, AnalyzerComponentBuilder:,代表可变成分正在建造的工作。这些都有配置属性、过滤要求,输入和输出列。

提示

了解不幸的相似性AnalyzerComponentBuilder的类名称和“AnalysisJobBuilder”类名。摆脱困惑,记住“分析”代表的全部范围的工作,而一个分析器是一个活跃的工作(“组件”)的一部分。

让我们看一个例子的编程工作。并确保我们不要错过重要的见解,我们将使它成为一个相当重要的工作与过滤器、变压器和分析器。这份工作将包括:

  1. ���源列的数据存储“数据库”:姓名、年龄和Company_name。

  2. 所有记录“Company_name”是空的位置插入到数据存储被称为“我的CSV文件”。在CSV文件中列被称为“fullname”和“age_years”。

  3. 所有记录在“Company_name”不是空1)会工作在另一个表的数据库地址抬头,和2)的名称和工作地址将被传递给一个模式仪分析仪。

Datastore myDatabase = configuration.getDatastoreCatalog().getDatastore("my database"); Datastore myCsvFile = configuration.getDatastoreCatalog().getDatastore("my CSV file"); AnalysisJobBuilder builder = new AnalysisJobBuilder(configuration); builder.setDatastore(myDatabase); builder.addSourceColumns("public.persons.Name","public.persons.Age","public.persons.Company_name") InputColumn<?> nameColumn = builder.getSourceColumnByName("Name"); InputColumn<?> ageColumn = builder.getSourceColumnByName("Age"); InputColumn<?> companyColumn = builder.getSourceColumnByName("Company_name"); // add a filter to check for null 'company' FilterComponentBuilder<NullCheckFilter> nullCheckBuilder = builder.addFilter(NullCheckFilter.class); nullCheckBuilder.addInputColumn(companyColumn); // add a InsertIntoTable analyzer to write the records without a company to the csv file AnalyzerComponentBuilder<InsertIntoTableAnalyzer> insertBuilder = builder.addAnalyzer(InsertIntoTableAnalyzer.class); insertBuilder.addInputColumns(nameColumn, ageColumn); insertBuilder.setConfiguredProperty("Datastore", myCsvFile); insertBuilder.setConfiguredProperty("Columns", new String[] {"fullname","age_years"}); insertBuilder.setRequirement(nullCheckBuilder.getOutcome(NullCheckFilter.Category.NULL)); // add a lookup for the company working address TransformerComponentBuilder<TableLookupTransformer> lookupBuilder = builder.addTransformer(TableLookupTransformer.class); lookupBuilder.addInputColumn(companyColumn); lookupBuilder.setConfiguredProperty("Datastore", myDatabase); lookupBuilder.setConfiguredProperty("Schema name", "public"); lookupBuilder.setConfiguredProperty("Table name", "companies"); lookupBuilder.setConfiguredProperty("Condition columns", new String[] {"name"}); lookupBuilder.setConfiguredProperty("Output columns", new String[] {"address"}); lookupBuilder.setRequirement(nullCheckBuilder.getOutcome(NullCheckFilter.Category.NOT_NULL)); // reference the 'working address' column and give it a proper name MutableInputColumn<?> addressColumn = lookupBuilder.getOutputColumns().get(0); addressColumn.setName("Working address"); // add the Pattern finder analyzer PatternFinder patternFinder = jobBuilder.addAnalyzer(PatternFinder.class); patternFinder.addInputColumns(nameColumn, addressColumn); // validate and produce to AnalysisJob AnalysisJob analysisJob = jobBuilder.toAnalysisJob();

从这个例子中注意事项:

  1. 注意使用.setRequirement的过滤需求设置成功组件(…)方法。

  2. 没有任何明确的过滤需求设置模式仪分析仪。这不是必要的,因为它取决于转换输入列(工作地址)本身的要求。DataCleaner将自动算出传递需求。

  3. 一块‘魔法’是如何正确设置组件的属性。我们可以看到,我们称之为 .setConfiguredProperty(字符串、对象),但不知道如何找出作为参数传递。有两个合适的方法算出来…

    1. 您可以使用DataCleaner命令行中列出所有组件的一个特定的类型,例如:

      > DataCleaner-console.exe -list ANALYZERS ... name: Insert into table - Consumes 2 named inputs Input columns: Additional error log values (type: Object) Input columns: Values (type: Object) - Property: name=Column names, type=String, required=true - Property: name=Datastore, type=UpdateableDatastore, required=true ...
    2. 或者你可以简单地打开组件类在IDE检查@Configured属性。例如,如果我们看看 InsertIntoTableAnalyzer.java我们将会看到:

      ... @Inject @Configured @Description("Names of columns in the target table.") @ColumnProperty String[] columnNames; @Inject @Configured @Description("Datastore to write to") UpdateableDatastore datastore; ...

      从这些领域我们可以推断出将有两个配置属性,“列名”和“数据存储”。

不管怎样,我们现在有了一个 AnalysisJob变量名称“analysisJob”。然后我们可以继续执行这项工作。

步骤3:执行

执行工作是最简单的步骤之一,但显然有选项之外的“香草”场景。

运行工作的简单的场景是使用普通AnalysisRunnerImpl类,像这样:

AnalysisRunner runner = new AnalysisRunnerImpl(configuration); AnalysisResultFuture resultFuture = runner.run(analysisJob);

这将返回一个 AnalysisResultFuture在大多数情况下,代表了一个仍在运行的工作。您的应用程序可以在后台继续做其他工作,或者它可以决定阻止通过调用 .await() .

这是一个典型的例子处理结果的未来:

// block until the job has finished resultFuture.await(); if (resultFuture.isSuccessful()) { // do something with the successful result handleResult(resultFuture); } else { List<Throwable> errors = resultFuture.getErrors(); for (Throable error : errors) { logger.error("An error occurred while executing job", error); } // usually the first error that occurred is the culprit, so we'll throw that one throw errors.get(0); }

你可能会问什么样的错误会发生在执行DataCleaner工作吗?答案是,它可以很多东西,例如:

  1. 连接到源数据库或资源可能会失败。

  2. 一个组件的工作可能会抛出一个意想不到的异常。

  3. 的一个组件可能会抛出一个异常,因为它的配置是不完整的或无效的(尽管这在大多数情况下会发现在构建AnalysisJob实例)。

  4. 如果你在写数据到另一个数据存储,也可能会因为任何datastore-dependent失败原因。

  5. 如果你的工作是做一些愚蠢的像十亿惟一id的值分布,然后你会耗尽内存。

现在让我们假设你的工作已成功执行。现在我们将看看如何后处理结果以及如何保存/加载/从一个文件中。

步骤4:结果

好,现在我们有一个 AnalysisResultFuture,我们认定它是成功的。我们能做些什么呢?

工作的每个分析器的结果可通过“AnalysisResult”接口,AnalysisResultFuture实现。注意,分析仪结果类型非常不同。例如,分析器生成一个“插入表格” WriteDataResult,而产生一种“模式仪”PatternFinderResult让我们来看看你可以从他们中提取信息:

// demonstrate the the result // future implements the AnalysisResult interface, which is sufficient // for all the followin operations AnalysisResult analysisResult = resultFuture; List<AnalyzerResult> results = analysisResult.getResults(); for (AnalyzerResult result : results) { if (result instanceof WriteDataResult) { WriteDataResult writeDataResult = (WriteDataResult)result; System.out.println("Inserted " + writeDataResult.getWrittenRowCount() + " records"); } if (result instanceof PatternFinderResult) { PatternFinderResult patternFinderResult = (PatternFinderResult)result; int matches = patternFinderResult.getMatchCount("Aaaaa Aaaaa") int total = patternFinderResult.getTotalCount(); System.out.println("There where " + matches + " matches out of " + total + " for our standard pattern."); } }

正如您可以看到的,你如何处理结果很大程度上取决于什么类型的结果。

通用的处理结果,包括所有可能的结果可能发生扩展,DataCleaner雇佣了渲染器渲染器框架,选择一个结果根据类型和优先级。如果你需要这样的通用功能,看看类RendererBean RendererFactory,渲染器和RenderingFormat。

一个共同的要求是坚持它。我们建议这样做通过Java序列化的,因为分析结果是多态的结构可能是依赖于扩展。设备还可以更“结构化”持续计划,但要注意,它将需要很长一段稳定分析程序添加到您的工作。

让我们看看我们如何使用Java序列化。但不幸的是 AnalysisResultFuture不是可序列化的!不过一个类,接口“AnalysisResult”与“AnalysisResultFuture”,是可序列化的,即“SimpleAnalysisResult”。让我们看看如何使用它和序列化结果.analysis.result。dat文件,(DataCleaner可以阅读):

// make the result serializeable AnalysisResult analysisResult = resultFuture; analysisResult = new SimpleAnalysisResult(analysisResult.getResultMap()); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my_result.analysis.result.dat")); oos.writeObject(analysisResult); oos.close();

例如,现在我们还被反序列化加载我们的文件。我们需要使用ChangeAwareObjectInputStream类,保证向后兼容的反序列化的对象:

ObjectInputStream ois = new ChangeAwareObjectInputStream(new FileInputStream("my_result.analysis.result.dat")); AnalysisResult analysisResult = (AnalysisResult) ois.readObject();

现在结果是恢复,你可以进一步的工作。

第25章。开发人员资源

表的内容

扩展开发教程
建筑DataCleaner

扩展开发教程

有很多有用的资源对于那些从事开发扩展(又名。DataCleaner插件/插件)。为了帮助你,这是一个有用的链接列表。如果你认为这个列表是失踪的一个链接,请让我们知道:

  1. 教程:开发一个变压器

  2. 教程:开发一个分析器

  3. 教程:实现一个自定义数据存储

  4. Javadoc:DataCleaner

  5. Javadoc:元模型

建筑DataCleaner

得到从GitHub DataCleaner的源代码:

> git clone https://github.com/datacleaner/DataCleaner.git DataCleaner

建设项目:

> cd DataCleaner > mvn clean install

运行DataCleaner

> cd desktop/ui/target > java -jar DataCleaner-desktop-ui-[version].jar

26章。扩展包装

文摘

DataCleaner扩展包的添加功能,用Java编写的。正确包一个扩展,本章将介绍细节。

表的内容

带注释的组件
单一JAR文件
扩展元数据的XML
组件的图标

带注释的组件

扩展在DataCleaner发现背后的主要原则是带注释的类。应该发现任何组件应该这两种注释:

  1. @java.inject.Named类,实现了变压器,滤波器或分析仪接口。

  2. @org.datacleaner.api.RendererBean——实现渲染器接口的类。

请参阅使用javadoc文档接口的详细信息。

单一JAR文件

扩展必须包含一个单独的JAR文件。如果你有依赖性以外提供的库DataCleaner分布,你需要包这些内部自己的JAR文件。如果你使用Maven构建、Maven插件组装可以提供这个功能很容易在POM中使用这个代码片段:

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2.1</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build>

扩展元数据的XML

改善经验,您可以选择关于扩展的元数据包含在一个XML文件,打包 JAR文件本身。

扩展元数据文件的名称 datacleaner-extension.xml和被放置在JAR文件的根目录。这里有一个例子的文件看起来像:

<extension xmlns="http://eobjects.org/datacleaner/extension/1.0"> <name>My extension</name> <package>path.to.extension</package> <description>This is an example extension. I should put a short description here.</description> <icon>path/to/extension/ExtensionIcon.png</icon> <author>John Doe</author> <url>http://datacleaner.org/extensions</url> <version>1.0</version> </extension>

这个元数据的附加值是DataCleaner公开这个信息给用户,也可以使用它来管理更新的扩展元数据文件等。然而,完全可选的。

组件的图标

如果你想为你的组件(如添加自定义图标。变压器或分析仪),您需要将图标为PNG图像具有相同名称的组件的完全分类的类名。

一个例子:如果你的组件类的名字是“com.company.ext.MyAnalyzer”,那么这个组件的图标应该位于“/com/company/ext/MyAnalyzer。png”扩展JAR文件。

同样,如果你包自己的ComponentCategory实现DataCleaner(定义菜单组),您可以定义为这些图标添加一个PNG文件,一个完全分类文件名对���ComponentCategory类名。

第27章。嵌入DataCleaner

可以将DataCleaner嵌入其他的Java应用程序。这允许一个简单的方法来添加数据质量分析(DQA中)图和数据分析功能添加到您正在构建的应用程序。

最简单的方式嵌入DataCleaner仅仅是通过什么DataCleaner主要可执行文件实例化 引导类使用默认参数:

BootstrapOptions bootstrapOptions = new DefaultBootstrapOptions(args); Bootstrap bootstrap = new Bootstrap(bootstrapOptions); bootstrap.run();

进一步定制,添加自己的实现 BootstrapOptions类。嵌入DataCleaner的主要场景是运行应用程序在所谓的“单数据存储模式”。这可以通过实现BootstrapOptions getSingleDatastore和提供一个非空值()方法。


原创粉丝点击