访问无模式数据的最佳实践是什么?

9
我正在研究RDF,特别是如何访问存储在rdf存储中的信息。与传统的关系型数据库相比,巨大的区别在于缺乏预定义的模式:在关系型数据库中,您知道表具有哪些列,并且可以从技术上将每行映射到类的实例。该类具有明确定义的方法和属性。
在无模式系统中,您不知道给定信息关联的数据是什么。这就像拥有一个带有任意数量未预定义列的数据库表,每行可以在任意数量的这些列中具有数据。
与对象关系映射器类似,还有对象RDF映射器。 RDFAlchemy和SuRF是我现在正在使用的两个。基本上,它们为您提供了一个资源对象,其方法和属性是动态提供的。这有点有道理...但是,这并不容易。在许多情况下,您更喜欢具有明确定义的接口,并且在设置和获取模型对象上的数据时更加控制。这种通用访问使事情变得困难,在某种意义上。
我注意到的另一件事(也是最重要的)是,即使在一般情况下,期望无模式数据提供关于资源的任意信息,但在实践中,您或多或少地知道“信息类别”倾向于在一起。当然,您不能排除附加信息的存在,但在某些情况下,这是例外,而不是规则,尽管异常足够敏感,以至于严格模式太具有破坏性。在文章的rdf表示(例如,在RSS / ATOM提要中)中,您知道所描述资源的术语,并且可以将它们映射到明确定义的对象。如果提供其他信息,则可以定义扩展对象(从基本对象继承),以提供对增强信息的访问器。因此,在某种意义上,您通过“面向模式的对象”来处理无模式数据,可以在需要查看特定附加信息时进行扩展。
我的问题与您在实际使用无模式数据存储方面的经验有关。它们如何映射到面向对象的世界,以便您可以熟练使用它们,而不会过于接近无模式存储的“裸金属”?(在RelDB术语中,不使用太多SQL并直接干涉表结构)
访问是否注定非常通用(例如,SuRF的“插入属性”是您可以访问数据的最高,最专业的级别),或者具有特定约定方便模式的专门类也是一种好方法,引入了访问新和意外关联数据的类繁殖的风险?

长度或复杂度? :P - Stefano Borini
4个回答

4
我想我的简短回答是“不要这样做”。我有一些经验,曾将XML数据映射到关系型数据库中。如果您决定使用这样的数据库,您需要不断验证数据。您还需要非常严格的纪律来避免出现共性很少的数据库。在这里使用模式会有所帮助,因为大多数XML模式都是面向对象的,因此可扩展,减轻了分析的需要,以避免创建具有不同名称但相似数据的情况,这将导致任何必须访问您的数据库的人对您产生恶意想法。
根据我的个人经验,如果您正在进行网络数据库可以胜任的工作,请继续。如果不是,您将失去关系型数据库可以执行的所有其他功能,例如完整性检查、事务和集合选择。然而,由于大多数人仅将关系型数据库用作对象存储器,因此我想该点无关紧要。
至于如何访问这些数据,只需将其放入Hashtable中即可。说真的。如果没有任何模式存在,则永远不会知道其中包含什么。如果您有一个模式,可以使用它来生成访问器对象,但您获得的很少,因为同时失去了底层存储的灵活性并获得了DAO(数据访问对象)的不灵活性。
例如,如果您有一个Hashtable,从XML解析器中获取值通常相当容易。您定义要使用的存储类型,然后遍历XML树并将值放入存储类型中,将类型存储在Hashtable或List中,具体取决于情况。但是,如果您使用DAO,则最终无法轻松扩展数据对象,这是XML的优势之一,并且必须为对象创建getter和setter。
public void setter(Element e) throws NoSuchElementException {
    try {
        this.Name = e.getChild("Name").getValue();
    } catch (Exception ex) {
        throw new NoSuchElementException("Element not found for Name: "+ex.getMessage());
    }
}

当然,你需要为模式层中的每个值都这样做,包括子层的加载器和定义。如果使用采用回调的更快的解析器,则最终会得到一个更大的混乱,因为您现在必须跟踪您所在的对象以生成结果树。
我已经完成了所有这些操作,尽管通常情况下我构建一个验证器,然后是提供XML和数据类之间匹配的适配器,然后是一个协调过程将其与数据库协调。不过,几乎所有代码最终都是自动生成的。如果您有DTD,则可以生成大部分访问它的Java代码,并且具有合理的性能。
最终,我建议将自由形式、网络化或分层数据保留为自由形式、网络化或分层数据。

2
我会说,对于一个无模式的XML文件来说,最好的做法就是为它创建一个模式!
没有模式并不是特别好的。这意味着您不能以任何方式验证文件,除非检测它是否为格式良好的XML。
完全没有语义似乎有点可疑。因为这意味着您不知道应该、已经或将要放入其中的内容。如果是这种情况,那么它听起来像是在寻找问题的解决方案。
如果您没有模式,因为您还不知道模式语言,请看一下DTD。它非常简单。如果您的应用程序中有验证实用程序或验证解析器,您可以在大约一两个小时内学习和掌握它。
如果阻止您拥有模式的问题是您的模式规则似乎不适合到目前为止查看的模式定义文件类型,不要担心。
虽然DTD甚至XSD(XML模式)文件有些不灵活,但还有其他更灵活的模式文件类型。它们比XSD简单得多,相信我。
请看一下RNC(RELAX NG,紧凑型)模式文件规范。RNC文件非常容易供人类阅读和编写。有一些XML编辑器可以理解它们。还有一些实用程序可以在RELAX NG格式(RNG或RNC)和其他格式(如DTD和XSD)之间进行转换。
上一次我检查时,XHTML TR包含了一个非规范性的RNC文件,以帮助验证它,更不用说明确记录它了。 RELAX NG具有这样的灵活性,您实际上可以在未成为Borg集体的一部分的情况下阅读它。在这种情况下,Borg不是指微软的委婉说法。
如果您需要比RELAX NG更灵活的东西,请瞥一眼Schematron。它是一种非常好的基于规则的模式验证语言。它并不是很复杂。像这些其他模式语言一样,它也存在已经很长时间了,是成熟且被公认的标准。
一些微软的高级工程师对XSD表示出了严重的疑虑。它的复杂性很高,事实证明它不能表达某些不太奇怪的数据排列,它非常冗长,它混合了验证和默认值等问题。无论你在做什么,它似乎都不适合直接支持。
像XSD绑定工具一样,RDF映射器非常适合持久化对象,并给出它们在某些支持的编程语言(如Java)中的类(例如使用JAXB)。但是,首先并不清楚您是否有要持久化的类。
还有一些语义Web技术,如OWL和RDF,它们非常灵活和动态。
您可能想看看的一个工具是斯坦福大学的Protege。它非常强大和灵活。它基本上是一个语义Web IDE和框架。后者是用Java编写的,而该工具也是如此。然而,Protege创建和编辑的语义Web模式和数据文件可以被任何语言编写的程序使用。这些文件没有对Java的偏见。
此外,您可以使用Swoogle找到许多语义Web模式。可能已经有一个适合您的应用程序的模式了。
基本上,一旦您知道要在XML数据文件中放置什么,就很容易用这些模式验证语言之一创建模式文件。如果您不知道,则程序或人读取时不太可能知道该怎么做。如果是这种情况,XML可能不是最好的存储表示形式。我不确定是否有其他更好的选择。
相反,您可能只想使用通用的动态类型脚本语言(如Python或Ruby)来执行您正在执行的操作。如果您希望程序不仅具有无限的数据格式,还可以修改自己,那么也可以使用LISP。
无模式数据存储的另一个选项是逻辑编程语言。这些通常没有任何模式,而是有一个本体论
我曾经大量使用的两种使用本体论的编程语言是CLIPS和Prolog。这两种语言都有免费、开源、跨平台的实现版本可用。
你可以看看SWI-Prolog,它快速、简单而强大。你可以在其中定义事实和规则,当需要时规则会合成相应的事实。你可以通过查询来提取数据。Prolog实际上是RDF在1990年代创建时的灵感来源,我记得原始的RDF文档经常引用Prolog。如果你想要“发现”、“分析”或“查找”本体中的事实,Prolog是编写此类应用程序的非常好的语言。它也很方便进行自然语言解析。
如果你想要对本体中的事实进行问题解决,那么CLIPS也很不错。它非常适合组织、故障排除和配置相关的应用程序。
如果模式不是你的菜,也许本体论是。如果不是,也许你应该使用动态类型脚本语言,并使用映射和列表将存储在复杂对象中的数据持久化到文件中,使用它们的标准持久化机制。

1

我没有使用过基于面向对象编程的无模式数据库,但我有多年使用无模式数据库和脚本的经验。

从我的经验来看,这种方法非常有用。我使用的数据库也是无类型的(所有字符串都是任意的)。这带来了以下优点:

  • 您不必担心数据库结构。如果您需要存储某些内容,只需存储即可。您不必担心数据类型是否适合脚本语言
  • 在需要时,您可以轻松地向“对象”添加调试信息,而不必为大多数表行留下空列。这使您甚至可以在需要时存储大块数据,
  • 您不必担心对数据库结构的更新。您只需将随新软件版本提供的新数据写入数据库即可。这样,您就不需要管理员更新表结构并转换旧数据。它会自动完成
  • 如果键-值对的键具有有意义的名称,则您不需要为数据编写太多文档

因此,在我的情况下,无模式数据库与脚本非常有用且取得了巨大成功。

当你考虑使用对象来进行无模式数据库时,我建议将对象存储在哈希表中以保持自由。这样可以让你自由地访问所有的键值对,无论选择哪个“对象”。它还可以让你自由地添加新的键值对。

如果你的对象(比如在 RSS 订阅中)有一个明确定义的基础,那么设计一个基础对象是有意义的,它封装了明确定义的基础,但也具有某种哈希映射以实现自由。

一旦你发现越来越多的键值对变成了“标准”,只需更新你的对象模型以封装这些内容,你的软件就会演化成正确的数据结构。在以后的某个时候,将一些数据移动到传统的关系型数据库系统中可能也是有意义的。

不要过度设计——需要时再实现功能...


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接