├── .gitignore ├── images ├── jena.png ├── creature.jpg ├── owl-01.png ├── owl-02.png ├── rdf-xml.png ├── protege-01.png ├── protege-02.png ├── protege-03.png ├── protege-04.png ├── protege-05.png ├── rdf-graph.jpg ├── rdf-graph.png ├── rdf-table.png ├── tdbloader.png ├── fuseki-edit.png ├── fuseki-info.png ├── fuseki-query.png ├── jena-webflow.jpg ├── rdf-example.png ├── s-get-graph.png ├── soh-scripts.png ├── sparql-insert.png ├── fuseki-catelog.png ├── s-query-result.png ├── fuseki-server-ui.png ├── jena-inf-figure2.png ├── reasoner-overview.png ├── sparql-entailment.png ├── sparql-example-01.png ├── sparql-example-02.png ├── sparql-example-03.png ├── sparql-example-04.png ├── sparql-example-05.png ├── sparql-example-06.png ├── sparql-example-07.png ├── sparql-example-08.png ├── sparql-example-09.png ├── sparql-example-10.png ├── sparql-example-11.png ├── sparql-example-12.png ├── sparql-example-13.png ├── sparql-example-14.png ├── sparql-example-15.png ├── sparql-example-16.png ├── sparql-example-17.png ├── sparql-example-18.png ├── sparql-example-19.png ├── sparql-example-20.png ├── sparql-example-21.png ├── sparql-example-22.png ├── sparql-example-23.png ├── sparql-example-24.png ├── sparql-example-25.png ├── tdbloader-results.png ├── fuseki-database-test.png ├── fuseki-upload-files.png ├── s-query-endpointURL.png ├── sparql-results-json.png ├── sparql-results-table.png ├── fuseki-create-database.png ├── fuseki-database-upload.png └── RDF-graph-protocol-model.jpg ├── data ├── demo.rules ├── sparql-example.ttl ├── demoData.rdf ├── example.rdf ├── owlDemoData.rdf ├── owlDemoSchema.owl └── Creatrue.ttl ├── sparql ├── insert.rq ├── select.rq ├── delete.rq └── federated-query.rq ├── notes ├── jena │ ├── arq.md │ ├── rdf-整理.md │ ├── rdf.md │ └── ontology.md ├── tdb-dynamic-dataset.md ├── sparql │ ├── sparql-advanced.md │ ├── 01文档约定.md │ ├── 03过滤器简介.md │ ├── 04SPARQL基础语法.md │ ├── 02查询入门.md │ ├── 05图模式.md │ ├── 06否定过滤器.md │ └── sparql.md ├── tool │ └── protege.md ├── reasoner.md ├── inference.md ├── tdb-assembler.md ├── semantic │ ├── owl-整理.md │ ├── owl.md │ └── rdf.md ├── fuseki.md └── tdb.md ├── rdf ├── RDFRead.java ├── RDFSelector.java ├── RDFBasis.java ├── RDFIterator.java └── RDFWrite.java ├── inference ├── RDFSData.java ├── InferenceExample.java ├── ReasonerExample.java ├── GenericRuleReasonerExample.java ├── InfModelStore.java └── OWLReasonerExample.java ├── tdb ├── TDBQueryExample.java └── TDBDatasetExample.java ├── ontology └── Basis.java ├── README.md └── arq └── QueryExample.java /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | .idea/ 3 | target/ 4 | *.iml 5 | dataset/ 6 | data/infmodel.ttl -------------------------------------------------------------------------------- /images/jena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/jena.png -------------------------------------------------------------------------------- /images/creature.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/creature.jpg -------------------------------------------------------------------------------- /images/owl-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/owl-01.png -------------------------------------------------------------------------------- /images/owl-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/owl-02.png -------------------------------------------------------------------------------- /images/rdf-xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/rdf-xml.png -------------------------------------------------------------------------------- /images/protege-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/protege-01.png -------------------------------------------------------------------------------- /images/protege-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/protege-02.png -------------------------------------------------------------------------------- /images/protege-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/protege-03.png -------------------------------------------------------------------------------- /images/protege-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/protege-04.png -------------------------------------------------------------------------------- /images/protege-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/protege-05.png -------------------------------------------------------------------------------- /images/rdf-graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/rdf-graph.jpg -------------------------------------------------------------------------------- /images/rdf-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/rdf-graph.png -------------------------------------------------------------------------------- /images/rdf-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/rdf-table.png -------------------------------------------------------------------------------- /images/tdbloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/tdbloader.png -------------------------------------------------------------------------------- /images/fuseki-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-edit.png -------------------------------------------------------------------------------- /images/fuseki-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-info.png -------------------------------------------------------------------------------- /images/fuseki-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-query.png -------------------------------------------------------------------------------- /images/jena-webflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/jena-webflow.jpg -------------------------------------------------------------------------------- /images/rdf-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/rdf-example.png -------------------------------------------------------------------------------- /images/s-get-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/s-get-graph.png -------------------------------------------------------------------------------- /images/soh-scripts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/soh-scripts.png -------------------------------------------------------------------------------- /images/sparql-insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-insert.png -------------------------------------------------------------------------------- /images/fuseki-catelog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-catelog.png -------------------------------------------------------------------------------- /images/s-query-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/s-query-result.png -------------------------------------------------------------------------------- /images/fuseki-server-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-server-ui.png -------------------------------------------------------------------------------- /images/jena-inf-figure2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/jena-inf-figure2.png -------------------------------------------------------------------------------- /images/reasoner-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/reasoner-overview.png -------------------------------------------------------------------------------- /images/sparql-entailment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-entailment.png -------------------------------------------------------------------------------- /images/sparql-example-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-01.png -------------------------------------------------------------------------------- /images/sparql-example-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-02.png -------------------------------------------------------------------------------- /images/sparql-example-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-03.png -------------------------------------------------------------------------------- /images/sparql-example-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-04.png -------------------------------------------------------------------------------- /images/sparql-example-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-05.png -------------------------------------------------------------------------------- /images/sparql-example-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-06.png -------------------------------------------------------------------------------- /images/sparql-example-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-07.png -------------------------------------------------------------------------------- /images/sparql-example-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-08.png -------------------------------------------------------------------------------- /images/sparql-example-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-09.png -------------------------------------------------------------------------------- /images/sparql-example-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-10.png -------------------------------------------------------------------------------- /images/sparql-example-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-11.png -------------------------------------------------------------------------------- /images/sparql-example-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-12.png -------------------------------------------------------------------------------- /images/sparql-example-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-13.png -------------------------------------------------------------------------------- /images/sparql-example-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-14.png -------------------------------------------------------------------------------- /images/sparql-example-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-15.png -------------------------------------------------------------------------------- /images/sparql-example-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-16.png -------------------------------------------------------------------------------- /images/sparql-example-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-17.png -------------------------------------------------------------------------------- /images/sparql-example-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-18.png -------------------------------------------------------------------------------- /images/sparql-example-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-19.png -------------------------------------------------------------------------------- /images/sparql-example-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-20.png -------------------------------------------------------------------------------- /images/sparql-example-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-21.png -------------------------------------------------------------------------------- /images/sparql-example-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-22.png -------------------------------------------------------------------------------- /images/sparql-example-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-23.png -------------------------------------------------------------------------------- /images/sparql-example-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-24.png -------------------------------------------------------------------------------- /images/sparql-example-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-example-25.png -------------------------------------------------------------------------------- /images/tdbloader-results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/tdbloader-results.png -------------------------------------------------------------------------------- /images/fuseki-database-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-database-test.png -------------------------------------------------------------------------------- /images/fuseki-upload-files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-upload-files.png -------------------------------------------------------------------------------- /images/s-query-endpointURL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/s-query-endpointURL.png -------------------------------------------------------------------------------- /images/sparql-results-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-results-json.png -------------------------------------------------------------------------------- /images/sparql-results-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/sparql-results-table.png -------------------------------------------------------------------------------- /images/fuseki-create-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-create-database.png -------------------------------------------------------------------------------- /images/fuseki-database-upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/fuseki-database-upload.png -------------------------------------------------------------------------------- /images/RDF-graph-protocol-model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangguixu/jena-learning/HEAD/images/RDF-graph-protocol-model.jpg -------------------------------------------------------------------------------- /data/demo.rules: -------------------------------------------------------------------------------- 1 | [transitiveRule: (?A demo:p ?B),(?B demo:p ?C) -> (?A demo:p ?C) ] 2 | [symmetricRule: (?Y demo:p ?X) -> (?X demo:p ?Y) ] -------------------------------------------------------------------------------- /sparql/insert.rq: -------------------------------------------------------------------------------- 1 | PREFIX foaf: 2 | INSERT DATA 3 | { 4 | foaf:knows [ foaf:name "Dorothy" ] . 5 | } ; -------------------------------------------------------------------------------- /sparql/select.rq: -------------------------------------------------------------------------------- 1 | PREFIX foaf: 2 | SELECT ?name (COUNT(?friend) AS ?count) 3 | WHERE { 4 | ?person foaf:name ?name . 5 | ?person foaf:knows ?friend . 6 | } GROUP BY ?person ?name -------------------------------------------------------------------------------- /sparql/delete.rq: -------------------------------------------------------------------------------- 1 | PREFIX foaf: 2 | DELETE { ?person foaf:name ?name } 3 | WHERE { 4 | foaf:knows ?person . 5 | ?person foaf:name ?name FILTER ( lang(?name) = "EN" ) . 6 | } -------------------------------------------------------------------------------- /sparql/federated-query.rq: -------------------------------------------------------------------------------- 1 | PREFIX foaf: 2 | SELECT ?name 3 | WHERE { 4 | foaf:knows [ foaf:name ?name ] . 5 | SERVICE { foaf:name ?name } 6 | } -------------------------------------------------------------------------------- /notes/jena/arq.md: -------------------------------------------------------------------------------- 1 | # ARQ 2 | 3 | ## 1. 简介 4 | 5 | ARQ是Jena中的一个SPARQL查询的处理器,支持: 6 | 7 | 1. 标准的SPARQL查询 8 | 2. 文本搜索(Lucene) 9 | 3. SPARQL中的更新操作 10 | 4. 支持SPARQL代数? 11 | 5. 支持自定义filter函数 12 | ... 13 | 14 | SPARQL algebra 15 | 16 | 17 | ## 2. SPARQL查询API 18 | 19 | [完整示例](../../arq/QueryExample.java) 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /notes/tdb-dynamic-dataset.md: -------------------------------------------------------------------------------- 1 | # TDB 动态数据集(Dynamic Datasets) 2 | 3 | TDB支持只查询TDB数据集下所有命名图的一个子集,从而提高查询效率。 4 | 5 | 在SPARQL查询语句中,可以通过关键字`FROM`和`FROM NAMED`来指定查询范围。其中 6 | 7 | * FROM:指的是默认图(多图合并还是默认) 8 | * FROM NAMED: 指定的是命名图 9 | 10 | *在ARQ模块中,没有对此查询语句的关键字进行区分,会在所有图中进行查询* 11 | 12 | 在TDB实现了对查询语句中的`FROM`和`FROM NAMED`的区分,有以下三种情况 13 | 14 | * 使用一到多个FROM,会使FROM后面的图合并为默认图(图合并) 15 | * 使用一到多个FROM NAMED,没有使用FROM,则会使用一个空的图作为默认图。 16 | * -------------------------------------------------------------------------------- /notes/jena/rdf-整理.md: -------------------------------------------------------------------------------- 1 | # RDF API 2 | 3 | ## 1. 类 4 | 5 | 在Jena中,我们用`Model`来表示一组RDF三元组数据。 6 | 7 | 我们知道RDF数据可以被解释为图(RDF Graph),依照这个角度,在Jean中定义了`RDFNode`类来表示RDF数据中的节点(即主体和客体)。 8 | 9 | 每个节点存储的值不同,因此设计了`RDFNode`的两个子类,来表示不同的值: 10 | 11 | * Resource,表示值为IRI资源的节点 12 | * Literal,表示值非IRI资源的节点,包括: 13 | 14 | * 字符串 15 | * 日期 16 | * 数值 17 | * XML Schema定义的数据类型 18 | 19 | 此外,RDFNode本身表示一个空节点(Blank Node)。 20 | 21 | 节点之间属性则是用类`Property`来表示。我们通过 22 | 23 | 在Jena中,我们可以用`Statement`类来表示一个三元组。 24 | -------------------------------------------------------------------------------- /notes/sparql/sparql-advanced.md: -------------------------------------------------------------------------------- 1 | # sparql 查询原理 2 | 3 | SPARQL提供强大的基于图形匹配的查询功能。 4 | 5 | 最简单的图形模式是三元组模式,一个三元组模式与RDF的三元组类型,不同的是三元组模式允许查询变量出现在主体、谓词或者客体的位置上,三元组模式合并形成一个基本的图形模式。 6 | 7 | ## 本体三元组映射 8 | 9 | 查询三元组并不能直接转化为本体三元组: 10 | 11 | 1. 查询三元组里面的词语都是用户的词语,并一定是本体知识库里面的术语 12 | 2. 查询三元组的结构与本体结构可能不同,因此需要利用用户词典与本体实体建立映射关系。 13 | 14 | ## 本体推理 15 | 16 | 利用本体推理,能够识别隐藏在本体概念之间的关系,本体中的基本关系有 17 | 18 | 1. part-of(部分整体关系) 19 | 2. kind-of(继承关系) 20 | 3. instance-of(实例关系) 21 | 4. attribute-of(属性关系) 22 | 23 | 基于本体上的关系属性有 24 | 25 | 1. equivalence(等价关系) 26 | 2. inherit(关系继承性) 27 | 3. symmetry(对称性) 28 | 4. transitivity(传递性) 29 | 30 | ## 节点的深度 31 | 32 | 由于节点的深度越大,概念之间的差别越小,因此概念也就是越具体。 33 | 34 | ## 节点的宽度 35 | 36 | 一个节点的兄弟节点越少,则这个概念越模糊,因此其模糊性与兄弟节点的个数成负相关。 -------------------------------------------------------------------------------- /data/sparql-example.ttl: -------------------------------------------------------------------------------- 1 | @prefix foaf: . 2 | @prefix rdfs: . 3 | a foaf:Person . 4 | foaf:name "Alice" . 5 | foaf:mbox . 6 | foaf:knows . 7 | foaf:knows . 8 | foaf:name "Bob" . 9 | foaf:knows . 10 | foaf:knows . 11 | foaf:name "Charlie" . 12 | foaf:knows . 13 | foaf:name "Snoopy"@en . -------------------------------------------------------------------------------- /data/demoData.rdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | ]> 8 | 9 | 14 | 15 | 16 | 17 | 18 |

19 | 20 | 21 | 22 |

23 | 24 | 25 | 26 |

27 | 28 | 29 | -------------------------------------------------------------------------------- /rdf/RDFRead.java: -------------------------------------------------------------------------------- 1 | import org.apache.jena.rdf.model.Model; 2 | import org.apache.jena.rdf.model.ModelFactory; 3 | import org.apache.jena.util.FileManager; 4 | 5 | import java.io.*; 6 | 7 | public class RDFRead { 8 | 9 | private static String fileName = "data/example.rdf"; 10 | private Model model; 11 | 12 | public Model getModel(){ 13 | return this.model; 14 | } 15 | 16 | public RDFRead(){ 17 | this.model = ModelFactory.createDefaultModel(); 18 | InputStream in = FileManager.get().open(fileName); 19 | 20 | if (in == null) { 21 | throw new IllegalArgumentException("File:" + fileName + " not found"); 22 | } 23 | model.read(in, ""); 24 | } 25 | 26 | public static void main(String []args){ 27 | 28 | Model model = new RDFRead().getModel(); 29 | 30 | model.write(System.out); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /rdf/RDFSelector.java: -------------------------------------------------------------------------------- 1 | import org.apache.jena.rdf.model.Model; 2 | import org.apache.jena.rdf.model.Resource; 3 | import org.apache.jena.vocabulary.VCARD; 4 | 5 | public class RDFSelector { 6 | 7 | static final String johnSmith = "http://somewhere/JohnSmith/"; 8 | 9 | public static void main(String []args){ 10 | 11 | Model model = new RDFRead().getModel(); 12 | 13 | model.write(System.out); 14 | 15 | // 获取John Smith的资源 16 | Resource vcard = model.getResource(johnSmith); 17 | 18 | // 获取名字 19 | Resource name = (Resource) vcard.getRequiredProperty(VCARD.N).getObject(); 20 | 21 | // 获取全名,会进行类型的转换 22 | String fullName = vcard.getRequiredProperty(VCARD.FN).getString(); 23 | 24 | // 添加为john smith添加昵称资源 25 | vcard.addProperty(VCARD.NICKNAME, "Smithy") 26 | .addProperty(VCARD.NICKNAME, "Adman"); 27 | 28 | 29 | 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /inference/RDFSData.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | import org.apache.jena.rdf.model.Model; 4 | import org.apache.jena.rdf.model.ModelFactory; 5 | import org.apache.jena.rdf.model.Property; 6 | import org.apache.jena.vocabulary.RDFS; 7 | 8 | public class RDFSData { 9 | private Model rdfsExample; 10 | public static final String NS = "urn:x-hp-jena:eg/"; 11 | 12 | public RDFSData() { 13 | /** 14 | * 生成一个数据集,有p和q两个属性, 15 | * 16 | * 其中p是q的子属性(RDFS定义) 17 | * 18 | * 此外添加一个三元组数据: a p foo 19 | */ 20 | this.rdfsExample = ModelFactory.createDefaultModel(); 21 | Property p = rdfsExample.createProperty(NS, "p"); 22 | Property q = rdfsExample.createProperty(NS, "q"); 23 | rdfsExample.add(p, RDFS.subPropertyOf, q); 24 | rdfsExample.createResource(NS+"a").addProperty(p, "foo"); 25 | } 26 | 27 | public Model getModel() { 28 | return this.rdfsExample; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /notes/jena/rdf.md: -------------------------------------------------------------------------------- 1 | # RDF API 2 | 3 | 完整的示例[在这里](../../rdf/) 4 | 5 | ## 1. 概述 6 | 7 | 在Jena中,由类`Model`来代表一个内存中的RDF数据模型。在Jena中采用工厂类ModelFactory的获取Model类的实例。 8 | 9 | Jena定义了一个接口`RDFNode`,用于表示客体或者主体,定义`Resource`类和`Literal`类继承`RDFNode`接口,分别用于表示IRI资源和非IRI资源(即字符串、数字、日期等)。 10 | 11 | 同时使用类`Property`来表示三元组中的谓词。 12 | 13 | `Statement`类则表示RDF的陈述,即为一个三元组。RDF API的使用示例如下: 14 | 15 | ```java 16 | // 使用工厂模式,创建一个model 17 | Model model = ModelFactory.createDefaultModel(); 18 | 19 | // 创建资源 20 | Resource r1 = model.createResource("http://example/r1"); 21 | Resource r2 = model.createResource("http://exmaple/r2"); 22 | 23 | // 创建一个属性来描述资源 24 | Property kindOf = model.createProperty("http://example/relation/kindOf", "kindOf"); 25 | 26 | // 组成一个三元组 27 | r1.addProperty(kindOf, r2); 28 | 29 | // 也可以直接声明一个三元组 30 | Statement s1 = model.createStatement(r1, kindOf, r2); 31 | model.add(s1); 32 | ``` 33 | 34 | ## 2. 数据遍历与查询 35 | 36 | ## 3. 模型操作 37 | 38 | ## 4. 持久化 39 | 40 | *同时,在RDF API中,还提供了模型数据的遍历和RDF内存模型持久化的方法。由于在工程中使用ARQ模块和数据库TDB,因此RDF API的这些方法没有多大的实际用处。* -------------------------------------------------------------------------------- /notes/sparql/01文档约定.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 1. 文档约定 8 | 9 | ### 1.1 命名空间(Namespaces) 10 | 11 | 在本文档中的例子前缀和对应的IRI为 12 | 13 | |Prefix|IRI| 14 | |:--|:--| 15 | |rdf:|http://www.w3.org/1999/02/22-rdf-syntax-ns#| 16 | |rdfs:|http://www.w3.org/2000/01/rdf-schema#| 17 | |xsd:|http://www.w3.org/2001/XMLSchema#| 18 | |fn:|http://www.w3.org/2005/xpath-functions#| 19 | |sfn:|http://www.w3.org/ns/sparql#| 20 | 21 | ### 1.2 数据描述 22 | 23 | 本文档中的所有rdf数据都采用[Turtle](https://www.w3.org/TR/turtle/)的语法来描述,这种描述可以很清晰地展示三元组,并且可以预定义前缀,缩短数据 24 | 25 | ``` 26 | @prefix dc: . 27 | @prefix : . 28 | :book1 dc:title "SPARQL Tutorial" . 29 | ``` 30 | 31 | ### 1.3 查询结果展示 32 | 33 | 本文档中所有查询结果展示为表格形式 34 | 35 | |x|y|z| 36 | |:--|:--|:--| 37 | |"Alice"|\|| 38 | 39 | ### 1.4 术语 40 | 41 | IRI: 就是URI 42 | Literal : 非IRI数据,例如字符串,数字,日期等等 43 | RDF Term:包括IRI,空白节点和Literals -------------------------------------------------------------------------------- /rdf/RDFBasis.java: -------------------------------------------------------------------------------- 1 | import org.apache.jena.rdf.model.Model; 2 | import org.apache.jena.rdf.model.ModelFactory; 3 | import org.apache.jena.rdf.model.Resource; 4 | import org.apache.jena.vocabulary.VCARD; 5 | 6 | public class RDFBasis { 7 | 8 | private String personURI = "http://somewhere/JohnSmith"; 9 | private String fullName = "John Smith"; 10 | private String givenName = "John"; 11 | private String familyName = "Smith"; 12 | private Model model; 13 | 14 | public Model getModel(){ 15 | return this.model; 16 | } 17 | 18 | public RDFBasis(){ 19 | this.model = ModelFactory.createDefaultModel(); 20 | 21 | Resource johnSmith = model.createResource(personURI); 22 | johnSmith.addProperty(VCARD.FN, fullName) 23 | .addProperty(VCARD.N, model.createResource() 24 | .addProperty(VCARD.Given, givenName) 25 | .addProperty(VCARD.Family, familyName)); 26 | 27 | } 28 | 29 | public static void main(String[] args) { 30 | 31 | Model model = new RDFBasis().getModel(); 32 | model.write(System.out); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rdf/RDFIterator.java: -------------------------------------------------------------------------------- 1 | import org.apache.jena.rdf.model.*; 2 | 3 | public class RDFIterator { 4 | 5 | public static void main(String []args){ 6 | 7 | 8 | Model model = new RDFBasis().getModel(); 9 | 10 | model.write(System.out); 11 | 12 | // 迭代器进行遍历 13 | StmtIterator iter = model.listStatements(); 14 | 15 | while(iter.hasNext()){ 16 | // 获取一个陈述,即三元组 17 | Statement stmt = iter.nextStatement(); 18 | // 分别获取,主体、属性和客体 19 | Resource subject = stmt.getSubject(); 20 | Property predicate = stmt.getPredicate(); 21 | // 客体可以是一个资源,也可以是一个文本, 22 | // 因此返回一个RDFNode,它是Resource和Literal的超类 23 | RDFNode object = stmt.getObject(); 24 | 25 | System.out.print(subject.toString()); 26 | System.out.print(predicate.toString()); 27 | if(object instanceof Resource){ 28 | System.out.print(object.toString()); 29 | } else { 30 | System.out.print("\"" + object.toString() + "\""); 31 | } 32 | System.out.println("."); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /notes/tool/protege.md: -------------------------------------------------------------------------------- 1 | # Protégé 2 | 3 | ## 1. 概述 4 | 5 | Protégé是一个开源智能系统本体编辑和知识获取框架,包括构建框架和本体(ontology)编辑器。 6 | 7 | 主页:http://protege.stanford.edu/ 8 | 下载(5.0.0):http://download.csdn.net/download/loveshouwang/8513995 9 | 10 | 此外,还要安装一个`graphviz`,可以直接[官网](http://www.graphviz.org/Download_linux_ubuntu.php)上下载。这个的作用是图形化我们所建立的本体。 11 | 12 | *官网上不去,只能用别人上传的资源* 13 | 14 | 在5.0.0版本的,有以下组成部分(跟owl一致): 15 | 16 | ![protege-01](../../images/protege-01.png) 17 | 18 | 19 | * entities 定义简写 20 | * classes 类 21 | * object Properties 对象属性 22 | * data properites 数据属性 23 | 24 | 25 | ## 2. 创建本体 26 | 27 | 以创建本体`Creature`为例子。 28 | 29 | ![creature.jpg](../../images/creature.jpg) 30 | 31 | 先点击`Classes`,然后在edit->create new,创建一个类`Creature`。这个就是所谓的`Domain Specific root class`. 32 | 33 | ![protege-02](../../images/protege-02.png) 34 | 35 | 然后在edit->create child,创建两个Creature的子类Plant和Animal 36 | 37 | ![protege-03](../../images/protege-03.png) 38 | 39 | 全部建立完成之后,点击OWLViz,就可以看到整体效果 40 | 41 | ![protege-04](../../images/protege-04.png) 42 | 43 | 创建结束之后,我们可以将这个本体导出,在file->save as 44 | 45 | ![protege-05](../../images/protege-05.png) 46 | 47 | 我们将这个作为数据,放入到[data](../../data)文件夹中,可以作为学习jena的ontology api的数据来源。 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /notes/reasoner.md: -------------------------------------------------------------------------------- 1 | # Reasoner 2 | 3 | [官方文档](http://jena.apache.org/documentation/inference/index.html#owl) 4 | 5 | ## 1. Reasoner实例的获取 6 | 7 | 两种方式获取Reasoner实例 8 | 9 | 1. 通过全局对象ReasonerRegistry的方法来获取一个Reasoner实例,例如以下获取一个RDFS类型的Reasoner 10 | 11 | ``` 12 | Reasoner reasoner = ReasonerRegistry.getRDFSReasoner(); 13 | ``` 14 | 15 | 2. 通过ReasonerFactory的theInstance()方法获取一个Reasoner实例,其中的create()可以对reasoner进行参数设置 16 | 17 | ``` 18 | Reasoner reasoner = RDFSReasonerFactory.theInstance().create(null); 19 | ``` 20 | 21 | [完整示例](../inference/ReasonerExample.java) 22 | 23 | ## 2. Reasoner参数设置 24 | 25 | ## 3. OWL Reasoner 26 | 27 | 28 | [完整示例](../inference/OWLReasonerExample.java) 29 | 30 | ## 4. Rule Engine 31 | 32 | Jena中包含了Rule Engine(规则引擎),它是实现RDFS和OWL推理器的基础,当然也可以用于实现自定义的推理器。 33 | 34 | 1. 这个规则引擎有自己的一套语法规则和结构,在定义规则之后,我们可以通过`GenericRuleReasoner`对象来构建推理器,然后应用到我们的数据集中。 35 | 36 | 2. 规则引擎支持前向推理和后向推理以及两种混合推理。 37 | 38 | ### 4.1 规则的语法和结构 39 | 40 | ### 4.2 Forward Chaining Engine(前向链式引擎) 41 | 42 | ### 4.3 Backward Chaining Engine(后向链式引擎) 43 | 44 | ### 4.4 Hybrid rule engine 45 | 46 | ![jena-inf-figure2.png](../images/jena-inf-figure2.png) 47 | 48 | 49 | ### 4.5 示例 50 | 51 | [完整示例](../inference/GenericRuleReasonerExample.java) 52 | 53 | 54 | -------------------------------------------------------------------------------- /data/example.rdf: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | John 7 | Smith 8 | 9 | 10 | 11 | Becky Smith 12 | 13 | 14 | Matthew 15 | Jones 16 | 17 | 18 | Sarah 19 | Jones 20 | 21 | 22 | 23 | Matt Jones 24 | 25 | 26 | Rebecca 27 | Smith 28 | 29 | 30 | 31 | Sarah Jones 32 | 33 | 34 | 35 | John Smith 36 | 37 | 38 | -------------------------------------------------------------------------------- /rdf/RDFWrite.java: -------------------------------------------------------------------------------- 1 | import org.apache.jena.rdf.model.InfModel; 2 | import org.apache.jena.rdf.model.Model; 3 | import org.apache.jena.rdf.model.ModelFactory; 4 | import org.apache.jena.reasoner.Reasoner; 5 | import org.apache.jena.reasoner.ReasonerRegistry; 6 | import org.apache.jena.riot.RDFDataMgr; 7 | import org.apache.jena.riot.RDFFormat; 8 | import org.apache.jena.util.FileManager; 9 | 10 | import java.io.File; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | 14 | 15 | /** 16 | * 将InfModel数据写入文件中 17 | * 18 | */ 19 | public class RDFWrite { 20 | 21 | public static void main(String []args) throws IOException { 22 | // 创建一个文件 23 | File f = new File("data/infmodel.ttl"); 24 | if(f.exists() == false) { 25 | f.createNewFile(); 26 | } 27 | // 通过文件对象创建输出流 28 | FileOutputStream fos = new FileOutputStream(f); 29 | 30 | 31 | // 可以将其视为本体库 32 | Model schema = FileManager.get().loadModel("data/owlDemoSchema.owl"); 33 | // 加载rdf数据 34 | Model data = FileManager.get().loadModel("data/owlDemoData.rdf"); 35 | 36 | // 获取推理器 37 | Reasoner reasoner = ReasonerRegistry.getOWLReasoner(); 38 | 39 | // 加入我们预先设置好的模式(本体库) 40 | reasoner = reasoner.bindSchema(schema); 41 | 42 | // 根据数据和reasoner,获取InfModel 43 | InfModel inf = ModelFactory.createInfModel(reasoner, data); 44 | 45 | // 将获取的InfModel保存下来 46 | RDFDataMgr.write(fos, inf, RDFFormat.TTL); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /notes/inference.md: -------------------------------------------------------------------------------- 1 | # Jena Inference 子系统 2 | 3 | ## 1. 概述 4 | 5 | Jena inference子系统是用于实现推理的功能。具体的结构如下: 6 | 7 | ![reasoner-overview](../images/reasoner-overview.png) 8 | 9 | 学习这个子系统,主要有以下几个方面: 10 | 11 | 1. InfModel对象,这个是由数据和推理器(reasoner)作为参数构建而成的模型,具有推理能力,也就是说我们最终都是通过对这个对象模型进行查询来获取我们的查询结果的。 12 | 13 | 2. Jena提供了四种类型的推理器 14 | 15 | 1. 可传递性的推理 16 | 2. RDFS规则推理 17 | 3. OWL、OWL Mini、OWL Micro Reasoner:实现了OWL/Lite的推理机制。 18 | 4. 自定义推理规则:支持用户自定义推理规则。 19 | 20 | 其中,前三种会内置在通过ModelFactory创建的模型中,例如createRDFSModel() 21 | 22 | 3. InfoModel对象实例的获取方式。 23 | 24 | 4. Reasoner对象实例的获取方式、推理器的参数设置 25 | 26 | 27 | 因此Jena Inference子系统分为两大部分 28 | 29 | 1. InfModel(本章内容) 30 | 2. [Reasoner](./reasoner.md) 31 | 32 | ## 2. 获取InfModel对象实例的方式 33 | 34 | 1. 结合内置的reasoner和数据直接获取InfModel对象实例 35 | 36 | ``` 37 | InfModel inf = ModelFactory.createRDFSModel(rdfsData); 38 | ``` 39 | 40 | 2. 先分别获取reasoner和数据,再取得InfModel对象实例 41 | 42 | ``` 43 | Reasoner reasoner = ReasonerRegistry.getRDFSReasoner(); 44 | InfModel inf = ModelFactory.createInfModel(reasoner, rdfsData); 45 | ``` 46 | 47 | [完整示例](../inference/InferenceExample.java) 48 | 49 | InfModel的本质是根据reasoner和data合成新的全面的rdf数据。注意两点: 50 | 51 | 1. 推理计算发生的时刻出现在结合reasoner和data返回新的RDF数据 52 | 2. 生成InfModel之后,后续的查询就仅仅是普通的查询。 53 | 54 | 我们在[示例](../inference/InfModelStore.java)中,将reasoner和data结合,生成的InfModel存储到文件`infmodel.ttl`中,打开文件可以看到本来就几条三元组数据被加上规则推理运算之后,扩充成了很多三元组数据。之后,我们通过读取`infmodel.ttl`文件,直接进行查询,就可以获取结果。 55 | 56 | ## 3. InfModel的属性方法 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /tdb/TDBQueryExample.java: -------------------------------------------------------------------------------- 1 | package tdb; 2 | 3 | import org.apache.jena.query.*; 4 | import org.apache.jena.rdf.model.Model; 5 | import org.apache.jena.tdb.TDB; 6 | import org.apache.jena.tdb.TDBFactory; 7 | 8 | /** 9 | * 查询数据库示例,运行的前提条件是 10 | * 11 | * 1. 运行TDBDatasetExample,创建了TDB数据,保存在根目录下的dataset 12 | * 2. 再使用tdbloader导入data目录下的sparql-example.ttl到TDB数据库中 13 | */ 14 | 15 | public class TDBQueryExample { 16 | 17 | public static void query(Model m){ 18 | // 编写查询语句, 19 | String queryString = "SELECT ?mbox " + 20 | "WHERE { " + 21 | "?p 'Alice' ." + 22 | "?p ?mbox ." + 23 | "}"; 24 | 25 | // 通过QueryFactory解析查询语句,获取Query对象 26 | Query query = QueryFactory.create(queryString); 27 | 28 | // 通过QueryExecution执行查询语句 29 | try (QueryExecution qexec = QueryExecutionFactory.create(query, m)) { 30 | // 获取查询之后的结果 31 | ResultSet results = qexec.execSelect(); 32 | 33 | // 格式化后,输出结果 34 | ResultSetFormatter.out(System.out, results, query); 35 | } 36 | } 37 | 38 | public static void main(String[]args) { 39 | // 建立连接 40 | Dataset dataset = TDBFactory.createDataset("dataset"); 41 | 42 | // 开始数据库操作 43 | dataset.begin(ReadWrite.READ); 44 | // 执行查询语句 45 | query(dataset.getDefaultModel()); 46 | // 数据库操作结束 47 | dataset.end(); 48 | 49 | // 释放资源 50 | TDB.closedown(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /data/owlDemoData.rdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | ]> 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /notes/sparql/03过滤器简介.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 3. RDF约束(RDF Term Constraints) 8 | 9 | 本章主要介绍的就是SPARQL中的`FILTERs`,可以对查询结果进行过滤。 10 | 11 | 示例数据 12 | 13 | ``` 14 | @prefix dc: . 15 | @prefix : . 16 | @prefix ns: . 17 | 18 | :book1 dc:title "SPARQL Tutorial" . 19 | :book1 ns:price 42 . 20 | :book2 dc:title "The Semantic Web" . 21 | :book2 ns:price 23 . 22 | ``` 23 | 24 | ### 3.1 过滤字符串(Restricting the Value of Strings) 25 | 26 | SPARQL中的`FILTERs`提供了`regex`(就是正则表达式)来匹配RDF literals(仅限于字符串类型),regex会进行test,返回结果为true的。(即过滤掉test为false的查询结果)。 27 | 28 | 例如查询title中包含"SPARQL"的结果 29 | 30 | ``` 31 | PREFIX dc: 32 | SELECT ?title 33 | WHERE { 34 | ?x dc:title ?title . 35 | FILTER regex(?title, "SPARQL") 36 | } 37 | ``` 38 | 39 | ![sparql-example-11.png](../../images/sparql-example-11.png) 40 | 41 | 42 | 这部分的查询跟regex知识比较密切,在regex函数(也可以叫表达式)中,也可以使用标志位`i`来表示忽略大小。 43 | 44 | ### 3.2 过滤数字(Restricting Numeric Values) 45 | 46 | 我们可以通过大小比较来过滤结果。例如我们获取数据中price\>30的结果,查询语句如下: 47 | 48 | ``` 49 | PREFIX dc: 50 | PREFIX ns: 51 | SELECT ?title ?price 52 | WHERE { 53 | ?x ns:price ?price . 54 | FILTER(?price > 30) 55 | ?x dc:title ?title . 56 | } 57 | ``` 58 | 59 | ![sparql-example-12.png](../../images/sparql-example-11.png) 60 | 61 | ### 3.3 其他的条件限制(Other Term Constraints) 62 | 63 | 除了数字之外,SPARQL还支持xsd:string,xsd:boolean,xsd:dateTime等类型的过滤。 64 | 65 | [支持的类型列表](https://www.w3.org/TR/sparql11-query/#operandDataTypes) 66 | 67 | 此外,还有其他很多方法可以运用在FILTER中,参考 68 | 69 | [函数定义](https://www.w3.org/TR/sparql11-query/#SparqlOps) -------------------------------------------------------------------------------- /inference/InferenceExample.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | import org.apache.jena.rdf.model.*; 4 | import org.apache.jena.reasoner.Reasoner; 5 | import org.apache.jena.reasoner.ReasonerRegistry; 6 | 7 | /** 8 | * 获取InfModel的方法 9 | */ 10 | 11 | public class InferenceExample { 12 | 13 | public void getInfModelByDefaultReasonerAndData(Model rdfsExample, String NS) { 14 | // 获取InfModel,这个模型会根据内置的reasoner处理数据 15 | InfModel inf = ModelFactory.createRDFSModel(rdfsExample); 16 | 17 | // 通过一个例子来说明reasoner的作用 18 | // 查询a q ?,在数据集中并没有直接的a q ?三元组数据,但是由于 19 | // 使用了reasoner,p是q的子属性,因此会转化为a p ?,返回结果 20 | Resource a = inf.getResource(NS+"a"); 21 | Property q = inf.getProperty(NS+"q"); 22 | System.out.println("Statement: " + a.getProperty(q)); 23 | } 24 | 25 | public void getInfModelByReasonerAndData(Model rdfsExample, String NS) { 26 | // 通过ReasonerRegistry对象的getRDFSReasoner来获取一个reasoner 27 | Reasoner reasoner = ReasonerRegistry.getRDFSReasoner(); 28 | // 通过数据和reasoner,来获取InfModel 29 | InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample); 30 | // 之后,进行同样的查询,效果是一致的 31 | Resource a = inf.getResource(NS+"a"); 32 | Property q = inf.getProperty(NS+"q"); 33 | System.out.println("Statement: " + a.getProperty(q)); 34 | } 35 | 36 | 37 | public static void main(String []args){ 38 | RDFSData data = new RDFSData(); 39 | InferenceExample infExample = new InferenceExample(); 40 | System.out.println("通过数据直接获取InfModel,此时内置默认的reasoner"); 41 | infExample.getInfModelByDefaultReasonerAndData(data.getModel(), data.NS); 42 | System.out.println("通过reasoner和数据来获取InfModel"); 43 | infExample.getInfModelByReasonerAndData(data.getModel(), data.NS); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /ontology/Basis.java: -------------------------------------------------------------------------------- 1 | package ontology; 2 | 3 | import org.apache.jena.ontology.OntClass; 4 | import org.apache.jena.ontology.OntModel; 5 | import org.apache.jena.ontology.OntModelSpec; 6 | import org.apache.jena.rdf.model.ModelFactory; 7 | 8 | import java.util.Iterator; 9 | 10 | public class Basis { 11 | 12 | public static void main (String[]args) { 13 | 14 | // 创建使用OWL语言的内存模型 15 | OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); 16 | 17 | // 加载模型 18 | ontModel.read("data/Creatrue.ttl"); 19 | 20 | // 定义一个类作为模型中的Animal类的等价类 21 | OntClass cls = ontModel.createClass("DongWuClass"); 22 | cls.addComment("the EquivalentClass of Animal..", "EN"); 23 | 24 | // 通过完整的URI取得模型中的Animal类 25 | OntClass oc = ontModel.getOntClass("http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Animal"); 26 | oc.addEquivalentClass(cls); 27 | 28 | // 迭代显示模型中的类, 29 | Iterator it = ontModel.listClasses(); 30 | while(it.hasNext()){ 31 | OntClass c = (OntClass)it.next(); 32 | // 如果不是匿名类 33 | if(!c.isAnon()){ 34 | System.out.print("Class"); 35 | 36 | // 获取类的URI,并输出 37 | // 在输出时,省略命名空间前缀 38 | System.out.println(c.getModel().getGraph().getPrefixMapping().shortForm(c.getURI())); 39 | } 40 | 41 | // 处理Animal类 42 | if(c.getLocalName().equals("Animal")) { 43 | System.out.println("URI@" + c.getURI()); 44 | System.out.println("Animal's EquivalentClass is" + c.getEquivalentClass()); 45 | 46 | // 输出等价类的注释 47 | System.out.println("[comments:" + c.getEquivalentClass().getComment("EN") + "]"); 48 | } 49 | } 50 | 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /inference/ReasonerExample.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | 4 | import org.apache.jena.rdf.model.*; 5 | import org.apache.jena.reasoner.Reasoner; 6 | import org.apache.jena.reasoner.ReasonerRegistry; 7 | import org.apache.jena.reasoner.rulesys.RDFSRuleReasonerFactory; 8 | 9 | /** 10 | * 获取reasoner,配置reasoner的方法示例 11 | */ 12 | 13 | public class ReasonerExample { 14 | 15 | public void getReasonerByReasonerRegistry(Model rdfsExample, String NS) { 16 | // 通过ReasonerRegistry对象的getRDFSReasoner来获取一个reasoner 17 | Reasoner reasoner = ReasonerRegistry.getRDFSReasoner(); 18 | // 通过数据和reasoner,来获取 19 | InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample); 20 | // 之后,进行推理查询 21 | Resource a = inf.getResource(NS+"a"); 22 | Property q = inf.getProperty(NS+"q"); 23 | System.out.println("Statement: " + a.getProperty(q)); 24 | } 25 | 26 | public void getReasonerByReasonerFactory(Model rdfsExample, String NS) { 27 | // 通过ReasonerFactory来获取reasoner 28 | Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null); 29 | // 通过数据和reasoner,获取InfModel 30 | InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample); 31 | 32 | // 进行推理查询 33 | Resource a = inf.getResource(NS+"a"); 34 | Property q = inf.getProperty(NS+"q"); 35 | System.out.println("Statement: " + a.getProperty(q)); 36 | } 37 | 38 | public static void main(String []args) { 39 | RDFSData data = new RDFSData(); 40 | ReasonerExample example = new ReasonerExample(); 41 | System.out.println("通过ResonerRegistry的方法来获取reasoner"); 42 | example.getReasonerByReasonerRegistry(data.getModel(), data.NS); 43 | System.out.println("通过ResonerFactory的方法来获取reasoner"); 44 | example.getReasonerByReasonerFactory(data.getModel(), data.NS); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /notes/jena/ontology.md: -------------------------------------------------------------------------------- 1 | # Ontology API 2 | 3 | 在Jena中,本体模型继承自Jena中的Model类。Model允许访问RDF数据集合中的陈述(Statements),OntModel对此进行了扩展,以便支持本体中的各种数据对象:类(classes)、属性(properties)、实例(个体individuals)。 4 | 5 | ## 1. 本体模型OntModel 6 | 7 | 本体模型(OntModel)是对Jena RDF模型的扩展(继承自RDF模型),提供了处理本体数据的功能。 8 | 9 | 使用Jena处理本体首先就是要建立一个本体模型,之后就能够通过本体模型中所定义的方法操作模型,比如导入子模型、获取模型中本体的信息、操作本体属性以及将本体的表示输出到磁盘文件等等。 10 | 11 | Jena通过model包中的ModelFactory创建本体模型,ModelFactory是Jena提供用来创建各种模型的类,在类中定义了具体实现模型的成员数据以及创建模型的二十多种方法。一个最简单的创建本体模型的语句如下: 12 | 13 | 14 | ``` 15 | OntModel ontModel = ModelFactory.createOntologyModel() 16 | ``` 17 | 18 | 该语句不含参数,应用默认设置创建一个本体模型ontModel,也就是说:它使用OWL语言、基于内存,支持RDFS推理。可以通过创建时应用模型类别(OntModelSpec)参数创建不同的模型,以实现不同语言不同类型不同推理层次的本体操作。 19 | 20 | 例如,下面的语句创建了一个使用DAML语言内存本体模型。直观地讲,内存模型就是只在程序运行时存在的模型,它没有将数据写回磁盘文件或者数据库表。 21 | 22 | ``` 23 | OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.DAML_MEM) 24 | ``` 25 | 26 | 我们所使用的本体是从OWL文件获得的,也就是说,是从磁盘读取的。读取的方法是调用Jena OntoModel提供的Read方法。例如 27 | 28 | ``` 29 | ontModel.read('Creature.owl'); 30 | ``` 31 | 32 | `read`方法有很多重载,方法如下 33 | 34 | ``` 35 | read( String url ); 36 | read( Reader reader, String base ); 37 | read( InputStream reader, String base ); 38 | read( String url, String lang ); 39 | read( Reader reader, String base, String Lang ); 40 | read( InputStream reader, String base, String Lang ); 41 | ``` 42 | 43 | ## 2. 文档管理器(Document Manager) 44 | 45 | 本体文档管理器(OntDocumentManager)是用来帮助管理本体文档的类,它包含了导入本体文档创建本体模型、帮助缓存下载网络上的本体等功能。 46 | 47 | 每个本体模型都有一个相关联的文档管理器。在创建本体模型时,可以创建独立的文档管理器并作为参数传递给模型工厂(ModelFactory)。 48 | 49 | 文档管理器有非常多的配置选项,基本可以满足应用的需求。首先,每个文档管理器的参数都可以通过Java代码来设置(注:OntDocumentManager有五种重载的构造函数)。另外,文档管理器也可以在创建的时候从一个RDF格式的策略文件读取相应设定值。 50 | 51 | 一个示例,创建一个本体,并且获取它的文档管理器。 52 | 53 | ``` 54 | OntModel m = ModelFactory.createOntologyModel(); 55 | 56 | OntDocumentManager dm = m.getDocumentManager(); 57 | ``` 58 | 59 | ## 3. 接口OntClass 60 | 61 | 这个接口中定义了本体种与概念(也就是类Class)相关的操作。 62 | 63 | OntoClass对概念之间的各种关系都有相应的定义方法,典型的有添加子类、添加约束、创建互斥概念、迭代返回某种类型的概念以及相关的逻辑判断等等。 64 | 65 | 例如通过ontModel中的listClasses()便可以返回模型中的所有概念组成的迭代器(Iterator),然后调用OntClass的各种方法具体进行操作。 66 | 67 | ## 4. 基本本体类型(OntResource) 68 | 69 | 所有本体API中用于表示本体的类继承自OntResource,这样就可以在OntResource中放置所有类公用的功能,并可以为一般的方法设置通用的返回值。Java接口OntResource扩展了Jena的RDF资源接口,所以任何可以接受资源或者RDFNode的方法都可以接受OntResource,并且也就可以接受任何其他本体值。 70 | 71 | [完整示例](../../ontology/Basis.java) 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /inference/GenericRuleReasonerExample.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | import org.apache.jena.rdf.model.*; 4 | import org.apache.jena.reasoner.Reasoner; 5 | import org.apache.jena.reasoner.rulesys.GenericRuleReasonerFactory; 6 | import org.apache.jena.util.FileManager; 7 | import org.apache.jena.util.PrintUtil; 8 | import org.apache.jena.vocabulary.ReasonerVocabulary; 9 | 10 | public class GenericRuleReasonerExample { 11 | 12 | public static void main(String[]args) { 13 | // 注册一个命名空间 14 | String demoURI = "http://jena.hpl.hp.com/demo#"; 15 | PrintUtil.registerPrefix("demo", demoURI); 16 | 17 | /** 18 | * 创建一个配置项,用于加载我们的规则,分为几步 19 | * 20 | * 1. 获取一个model,作用是创建Resource 21 | * 2. 通过model获取Resource类的示例,这个就是我们的配置项 22 | * 3. 配置项通过addProperty添加属性,设置rule的模式为hybrid 23 | * 4. 同样的方法,配置项,添加我们的规矩集 24 | */ 25 | Model m = ModelFactory.createDefaultModel(); 26 | Resource conf = m.createResource(); 27 | conf.addProperty(ReasonerVocabulary.PROPruleMode, "hybrid"); 28 | conf.addProperty(ReasonerVocabulary.PROPruleSet, "data/demo.rules"); 29 | 30 | // 生成一个GenericRuleReasoner的实例,并且传入配置项 31 | Reasoner reasoner = GenericRuleReasonerFactory.theInstance().create(conf); 32 | 33 | // 加载测试数据 34 | Model data = FileManager.get().loadModel("data/demoData.rdf"); 35 | 36 | // 根据reasoner和data,生成infModel 37 | InfModel inf = ModelFactory.createInfModel(reasoner, data); 38 | 39 | /** 40 | *在规则集中,我们定义了两条规则: 41 | * 42 | * 1. (?A demo:p ?B), (?B demo:p ?C) -> (?A > demo:p ?C) 43 | * 2. (?Y demo:p ?X) -> (?X demo:p ?Y) 44 | * 45 | * 在数据集中,我们有数据 46 | * a demo:p b 47 | * c demo:p a 48 | * b demo:p d 49 | * 50 | * 那么根据规则2,我们就可以推理出 51 | * b demo:p a 52 | * a demo:p c 53 | * d demo:p b 54 | * 55 | * 根据规则1,我们可以推理出 56 | * (b demo:p a)(a demo:p c) -> (b demo:p c) 57 | * ..... 58 | */ 59 | // 我们来查询所有a demo:p 的情况,列出所有的三元组 60 | Property p = data.getProperty(demoURI, "p"); 61 | Resource a = data.getResource(demoURI + "a"); 62 | 63 | StmtIterator i = inf.listStatements(a, p, (RDFNode) null); 64 | while(i.hasNext()) { 65 | System.out.println(" - " + PrintUtil.print(i.nextStatement())); 66 | } 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /notes/tdb-assembler.md: -------------------------------------------------------------------------------- 1 | # TDB Assembler 2 | 3 | `Assembler`是Jena中一个普遍应用的机制,用来描述建立的数据对象(模型或者数据集)。 4 | 5 | ## 1. 构建数据集 6 | 7 | 我们可以通过一个`assembler`文件来构建一个数据集(文件后缀为.ttl),可以在fuseki的项目中找到,在`run/configuration`中。文件还是以`Turtle`的语法来编写,我们以官网上的示例来讲解每一部分的含义。 8 | 9 | 10 | 11 | ``` 12 | @prefix tdb: . 13 | @prefix rdf: . 14 | @prefix rdfs: . 15 | @prefix ja: . 16 | 17 | [] ja:loadClass "org.apache.jena.tdb.TDB" . 18 | tdb:DatasetTDB rdfs:subClassOf ja:RDFDataset . 19 | tdb:GraphTDB rdfs:subClassOf ja:Model . 20 | 21 | <#dataset> rdf:type tdb:DatasetTDB ; 22 | tdb:location "DB" ; 23 | . 24 | ``` 25 | 26 | 27 | 1. 声明接下来文件中要使用的前缀:`@prefix` 28 | 2. 描绘TDB的情况,其中`[] ja:loadClass "org.apache.jena.tdb.TDB"`会加载TDB,并且初始化TDB。 29 | 3. 最后是一个TDB数据的描述,首先是一个tbd的数据集,然后还有它的数据集的存储位置。(文件存储)。 30 | 31 | ## 2. 合并默认图(Union Default Graph) 32 | 33 | 在`assembler`文件中,我们可以设置默认图的是数据集中命名图的合并,即非原来的默认图,只需要添加`tdb:unionDefaultGraph`。 34 | 35 | ``` 36 | <#dataset> rdf:type tdb:DatasetTDB ; 37 | tdb:location "DB" ; 38 | tdb:unionDefaultGraph true ; 39 | . 40 | ``` 41 | 42 | ## 3. 选择特定的rdf图 43 | 44 | 一个TDB数据集中一般有多个图,很有可能我们只使用到其他的一个。一般来说,如果我们只使用到TDB数据集的一个图,那么这个图就是`默认图`(会与命名图隔离开来)。 45 | 46 | 我们也可以指定一个命名图 47 | 48 | ``` 49 | <#graphNamed> rdf:type tdb:GraphTDB ; 50 | tdb:dataset <#dataset> . 51 | tdb:graphName ; 52 | . 53 | ``` 54 | 55 | ## 4. 多图合并为数据集 56 | 57 | 我们可以根据多个图数据来创建一个数据集(注意,此时的查询可能效率会很低) 58 | 59 | ``` 60 | @prefix tdb: . 61 | @prefix rdf: . 62 | @prefix rdfs: . 63 | @prefix ja: . 64 | 65 | [] ja:loadClass "org.apache.jena.tdb.TDB" . 66 | tdb:DatasetTDB rdfs:subClassOf ja:RDFDataset . 67 | tdb:GraphTDB rdfs:subClassOf ja:Model . 68 | 69 | # A dataset of one TDB-backed graph as the default graph and 70 | # an in-memory graph as a named graph. 71 | <#dataset> rdf:type ja:RDFDataset ; 72 | ja:defaultGraph <#graph> ; 73 | ja:namedGraph 74 | [ ja:graphName ; 75 | ja:graph <#graph2> ] ; 76 | . 77 | 78 | <#graph> rdf:type tdb:GraphTDB ; 79 | tdb:location "DB" ; 80 | . 81 | 82 | <#graph2> rdf:type ja:MemoryModel ; 83 | ja:content [ja:externalContent ] ; 84 | . 85 | ``` 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 语义技术与Jena框架 2 | 3 | ## Jena简介 4 | 5 | Jena是一个免费的、开源的Java平台上语义网开发框架。最初是由惠普实验室(HPL)的BrianMcBride开发,后来Jena称为Apache开源项目之一。 6 | 7 | ![jena](./images/jena.png) 8 | 9 | 结合整体架构图和Jena的官方文档,可以看到Jena框架共分为几大模块: 10 | 11 | * RDF API(RDF模型操作相关) 12 | * Ontology API(OWL本体模型操作相关) 13 | * ARQ(SPARQL标准的实现) 14 | * Inference API(本体推理的实现) 15 | * TDB(RDF数据的存储数据库) 16 | 17 | 此外Jena还提供了非常实用的命令行工具(例如SPARQL查询、批量导入RDF数据等)和一个基于Jena框架构建的Web应用程序Fuseki。 18 | 19 | *学习Jena框架,一定要结合对于的语义技术的知识,这样才能更加快速地上手。* 20 | 21 | ## Jena框架的各个模块 22 | 23 | 1. RDF API 24 | 25 | * [RDF简介](./semantic/rdf.md) 26 | * [RDF API使用示例](./jena/rdf.md) 27 | 28 | 2. Ontology API 29 | 30 | * [owl](./notes/semantic/owl.md) 31 | * [Protégé](./notes/tools/protege.md) 32 | * [Ontology API](./notes/jena/ontology.md) 33 | 34 | 3. Inference API 35 | 36 | * [inference](./notes/inference.md) 37 | * [reasoner](./notes/reasoner.md) 38 | 39 | 4. ARQ 40 | 41 | * [SPARQL](./notes/sparql) 42 | * [ARQ](./notes/jena/arq.md) 43 | 44 | 5. [TDB](./notes/tdb.md) 45 | 46 | * [TDB Assembler](./notes/tdb-assember.md) 47 | * [TDB Dynamic Datasets](./notes/tdb-dynamic-dataset.md) 48 | 49 | ## Fuseki 50 | 51 | [Fuseki](./notes/fuseki.md) 52 | 53 | ## Jena的整体web流程框架 54 | 55 | ![jena-complete](./images/jena-webflow.jpg) 56 | 57 | 58 | ## 代码示例 59 | 60 | 建议使用[Intellij IDEA](http://www.jetbrains.com/idea/#chooseYourEdition),安装社区版即可。 61 | 62 | 1. 需要下载[jena](http://jena.apache.org/download/index.cgi),解压之后,在项目中引入jena的包(在解压目录下的lib,全部引入) 63 | 2. 需要Java 8, 64 | 65 | 示例: 66 | 67 | 1. [RDF API](./rdf) 68 | 2. [Ontology API](./ontology) 69 | 3. [Inference API](./inference) 70 | 4. [ARQ](./arq) 71 | 5. [TDB](./tdb) 72 | 73 | ## 学习资料汇总 74 | 75 | 1. [Jena官网](http://jena.apache.org/index.html) 76 | 2. [sparql](https://www.w3.org/TR/sparql11-query/) 77 | 3. [如何在ecplise中使用Jena](http://www.iandickinson.me.uk/articles/jena-eclipse-helloworld/) 78 | 4. [Jena资料整理博客](http://www.itdadao.com/tags/jena-0.html) 79 | 5. [Jena API文档](http://jena.apache.org/documentation/javadoc/jena/) 80 | 6. [OWL](https://www.w3.org/TR/2004/REC-owl-features-20040210/) 81 | 7. [owl本体语言学习笔记](http://blog.sina.com.cn/s/blog_6a7447840100utms.html) 82 | 8. [Jena的Ontology学习](http://blog.csdn.net/zhang6560329/article/details/27095197) 83 | 9. [Protégé中文教程](http://wenku.baidu.com/link?url=5Wb66TcG8jSBImBTIxriCUp6KaYd6sLZ20SS4emUgjyVs14GegIVKmGVlM7CSs56p0eQ6vpHnlph3eGgUsKHmsma8GREPc-iPR9cRDwHmLW) 84 | 10. [Protégé构建本体教程](http://wenku.baidu.com/link?url=TcDAyKe0DzP38i6sGG70s8P4lCvaQ5RptO1iuX1n1ljPtIluBloeu4NfJVi1sFQVBeJ0O1d2I4U9_9RDa3n5jtlcB5eSVuFMioQvnEgConG) 85 | 11. [rdf数据模型下载](http://semanticweb.org/wiki/Main_Page.html) -------------------------------------------------------------------------------- /inference/InfModelStore.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | import org.apache.jena.rdf.model.InfModel; 4 | import org.apache.jena.rdf.model.Model; 5 | import org.apache.jena.rdf.model.ModelFactory; 6 | import org.apache.jena.rdf.model.Resource; 7 | import org.apache.jena.reasoner.Reasoner; 8 | import org.apache.jena.reasoner.ReasonerRegistry; 9 | import org.apache.jena.riot.RDFDataMgr; 10 | import org.apache.jena.riot.RDFFormat; 11 | import org.apache.jena.util.FileManager; 12 | import org.apache.jena.vocabulary.RDF; 13 | 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.io.IOException; 17 | 18 | /** 19 | * 我们通过reasoner和data来获取的InfModel。 20 | * InfModel的实质就是根据已有的规则和数据合成了新的全面的RDF数据。 21 | * 因此它可以被存储,读取,查询。 22 | * 也就是说reasoner应用于Data的时刻在于生成InfModel,后面的查询都不涉及运算。 23 | */ 24 | public class InfModelStore { 25 | 26 | /** 27 | * 生成InfModel,将其存储到文件中 28 | * 29 | * @throws IOException 30 | */ 31 | public static void write() throws IOException { 32 | // 创建一个文件 33 | File f = new File("data/infmodel.ttl"); 34 | if(f.exists() == false) { 35 | f.createNewFile(); 36 | } 37 | // 通过文件对象创建输出流 38 | FileOutputStream fos = new FileOutputStream(f); 39 | 40 | 41 | // 可以将其视为本体库 42 | Model schema = FileManager.get().loadModel("data/owlDemoSchema.owl"); 43 | // 加载rdf数据 44 | Model data = FileManager.get().loadModel("data/owlDemoData.rdf"); 45 | 46 | // 获取推理器 47 | Reasoner reasoner = ReasonerRegistry.getOWLReasoner(); 48 | 49 | // 加入我们预先设置好的模式(本体库) 50 | reasoner = reasoner.bindSchema(schema); 51 | 52 | // 根据数据和reasoner,获取InfModel 53 | InfModel inf = ModelFactory.createInfModel(reasoner, data); 54 | 55 | // 将获取的InfModel保存下来 56 | RDFDataMgr.write(fos, inf, RDFFormat.TTL); 57 | } 58 | 59 | /** 60 | * 从文件中读取InfModel(其实就是普通的rdf数据) 61 | * 进行查询。 62 | * 63 | */ 64 | public static void read() { 65 | Model inf = FileManager.get().loadModel("data/infmodel.ttl"); 66 | 67 | System.out.println("查询示例: 实例识别"); 68 | Resource gamingComputer = inf.getResource("urn:x-hp:eg/GamingComputer"); 69 | Resource whiteBox = inf.getResource("urn:x-hp:eg/whiteBoxZX"); 70 | if(inf.contains(whiteBox, RDF.type, gamingComputer)) { 71 | System.out.println("White box recognized as gaming computer"); 72 | } else { 73 | System.out.println("Failed to recognize white box correctly"); 74 | } 75 | } 76 | 77 | 78 | public static void main(String []args) throws IOException { 79 | System.out.println("写入infModel数据到文件中"); 80 | write(); 81 | System.out.println("读infModel数据,然后进行查询"); 82 | read(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /notes/semantic/owl-整理.md: -------------------------------------------------------------------------------- 1 | # 本体与OWL简介 2 | 3 | ## 1. 本体 4 | 5 | 本体(ontology)是一个哲学术语,是概念模型的明确的规范说明。 6 | 7 | 本体的目标是获取相关的领域知识,提供对该领域知识的共同理解,确定该领域内共同认可的词汇,并从不同层次的形式化模式上给出这些词汇(术语)和词汇间相互关系的明确定义。 8 | 9 | ### 1.1 本体的构建规则 10 | 11 | * 清晰性:由于知识是通过与其相关的概念和关系来表达,因此在创建本体必须满足清晰、明确地表达概念的要求,而不能被具体的上下文所干扰。这就要求我们必须对要创建的本体的领域知识有全面的了解,然后才能从客观上定义本体中的概念。 12 | * 一致性:本体是对概念知识的模型建立,因此要求在表达知识时,定义的概念必须具有一致性,定义的推理也具有一致性,即定义的概念知识和推理的结果不能前后出现矛盾。 13 | * 可扩展性:除了考虑到领域内公认的概念知识外,定义本体时还应该为本体的扩展提供有力的支持。例如要在现有的本体概念中添加新的概念或实例,则需要在不更改原有本体的基础上小范围修改就能满足该要求。 14 | * .编码偏好程度最小:实际系统中的编码很有可能不同,因此本体不应该使用某种特殊的编码方法。 15 | * 最小本体约束:本体需要对待建模对象有最小约束,来支持想要的知识共享活动。所依一个本体应该尽量少对建模发表声明,这样我们可以自由地对本体进行详细说明和实例化。 16 | 17 | 然而这5条准则是很难同时都被满足的,实际创建本体的过程中通常要同时权衡这5条准则。例如,考虑到清晰性原则就应该限制可能的词汇互通;而最小本体约定原则却要求指定一个弱理论,允许更多地建模。这两个准则并不矛盾。清晰性原则主要针对概念定义,而本体约束主要针对概念的描述。 18 | 19 | ### 1.2 本体的分类 20 | 21 | 本体是存在层次结构的。依赖本体的详细程度和领域依赖度的不同,Guarino提出了对本体的划分准则。 22 | 23 | 依照对本体的描述详细程度可以分为: 24 | 25 | * 参考本体(Reference Ontology):本体的描述详细程度高 26 | * 共享本体(Share Ontology):本体的描述详细程度低 27 | 28 | 依照领域依赖程度从低到高,可以把本体划分为: 29 | 30 | * 顶级本体(Top-Level Ontology),它描述的是最普遍的概念、概念之间的关系,如时间、行为、空间等等与具体事物应用无关的,是本体中层次最高的,适应性最高的; 31 | * 领域本体(Domain Ontology),描述特定领域中的概念和概念之间的关系,比顶级本体要低一个层次; 32 | * 任务本体(Task Ontology),描述特定任务的概念与它们之间的关系; 33 | * 最底层的是应用本体(Application Ontology),描述依赖于特定领域下的特定任务的概念及概念之间的关系。 34 | 35 | ### 1.3 本体的建模元语 36 | 37 | 本体有5个基本构成元素,这些元素分别是: 38 | 39 | * Classes(类) 或 Concepts(概念) 40 | 41 | 表示对象的集合,其定义采用框架结构,包含概念的名称、与其他概念之间的关系,概念的自然语言描述。 42 | 43 | 44 | * Relations(关系) 45 | 46 | 指的是领域中概念之间的交互作用,基本的关系有4种:part-of、kind-of、instance-of和attribute-of。part-of指的是概念之间整体与部分之间的关系;kind-of表达概念之间的继承关系,类似于父类、子类之间的关系;instance-of表达实例与概念之间的关系,类似于类和对象之间的关系;attribute-of指的是一个概念是另一个概念的属性。 47 | 48 | * Functions(函数) 49 | 50 | 一类特殊的关系。该关系中的前n-1个元素可以唯一决定第n个元素。例如说Father-of(x, y)表示y是x的父亲,而Father-of就是一个函数,可以通过x可以唯一确定他的父亲y 51 | 52 | * Axioms(公理) 53 | 54 | 永远为真的断言。 55 | 56 | * Instances(实例) 57 | 58 | 概念或者类所指的具体实体。 59 | 60 | 61 | ## 2. 本体语言OWL 62 | 63 | OWL是一种本体描述语言,用于描述文档的信息供应用程序理解和使用。它能够明确地表示一个概念(term)的意义和概念之间的关系。 64 | 65 | ### 2.1 OWL子语言 66 | 67 | OWL提供三种子语言(语言表达能力逐渐增强): 68 | 69 | * OWL Lite从 语法上来说,OWL-Lite是三个之中最简单的一个,当你的本体中类的层次结构很简单,并且只有简单的约束(constraint)时适合使用它来描述本体 70 | * OWL DL 和 OWL-Lite相比,OWL-DL的表达能力要丰富许多,它的基础是描述逻辑(Description Logics,即DL的由来)。描述逻辑是一阶逻辑(First Order Logic)的一个可判定的变种(译注:不一定准确,原文decidable fragment),因此可以用来进行自动推理,计算机从而可以知道本体中的分类层次,以及本体中的各种概念是否一致 71 | * OWL Full是OWL的三种子语言中表达能力最强的一个,适合在那些需要非常强的表达能力,而不用太关心可判定性(decidability)或是计算完全性的场合下使用。不过也正是由于表达能力太强这个原因,用OWL-Full表示的本体是不能进行自动推理的。 72 | 73 | 这三种子语言是包含关系,分别是OWL Full>OWL DL>OWL Lite,OWL Full是最大的集合。 74 | 75 | ### 2.2 OWL基础词汇 76 | 77 | 在OWL中,包含着一些基础的词汇,这些在构建本体的时候非常有用。 78 | 79 | |词汇|作用| 80 | |:--|:--| 81 | |owl:Ontology|声明一个本体| 82 | |owl:Class|定义一个类| 83 | |rdfs:subClassOf|定义一个类的子类| 84 | |owl:Thing|内置的类,作为所有类的父类| 85 | |owl:ObjectProperty|定义对象属性| 86 | |rdfs:domain|定义属性的定义域| 87 | |owl:DatatypeProperty|定义数值类型的属性| 88 | |rdfs:range|定义属性的值域| 89 | |owl:FunctionalProperty|定义函数类型的属性| 90 | |owl:inverseOf|表示两个属性是互逆| 91 | |rdfs:ID|定义所描述概念的名称| 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /data/owlDemoSchema.owl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | ]> 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 1 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /arq/QueryExample.java: -------------------------------------------------------------------------------- 1 | package arq; 2 | 3 | import org.apache.jena.query.*; 4 | import org.apache.jena.rdf.model.Model; 5 | import org.apache.jena.rdf.model.Resource; 6 | import org.apache.jena.util.FileManager; 7 | 8 | /** 9 | * ARQ中基础查询的例子,学习如何解析SPARQL查询语句,并且执行查询 10 | * 11 | * 关键类有 12 | * 13 | * 1. Query 14 | * 2. QueryFactory 15 | * 3. QueryExecution 16 | * 4. QueryExecutionFactory 17 | * 5. DatasetFactory 18 | * 19 | * 查询之后,返回结果中的涉及的关键类有 20 | * 21 | * 1. QuerySolution 22 | * 2. ResultSet 23 | * 3. ResultSetFormatter 24 | */ 25 | 26 | public class QueryExample { 27 | 28 | // 完整的解析->查询->处理结果流程 29 | public static void query() { 30 | // 加载数据 31 | Model model = FileManager.get().loadModel("data/sparql-example.ttl"); 32 | 33 | // 编写查询语句,可以看到挺麻烦的 34 | String queryString = "SELECT ?mbox " + 35 | "WHERE { " + 36 | "?p 'Alice' ." + 37 | "?p ?mbox ." + 38 | "}"; 39 | 40 | // 通过QueryFactory解析查询语句,获取Query对象 41 | Query query = QueryFactory.create(queryString); 42 | 43 | // 通过QueryExecution执行查询语句 44 | try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) { 45 | // 获取查询之后的结果 46 | ResultSet results = qexec.execSelect(); 47 | 48 | // 遍历结果,进行处理 49 | for(; results.hasNext() ; ) { 50 | // 获取每一条查询结果 51 | QuerySolution soln = results.nextSolution(); 52 | Resource r = soln.getResource("mbox"); 53 | // RDFNode x = soln.get("varName") 54 | // Literal l = soln.getLiteral("varL") 55 | System.out.println("查询结果为:" + r.toString()); 56 | } 57 | } 58 | } 59 | 60 | // 上面的步骤可以简化成以下的 61 | public static void simplifyQuery() { 62 | // 加载数据 63 | Model model = FileManager.get().loadModel("data/sparql-example.ttl"); 64 | 65 | // 编写查询语句,可以看到挺麻烦的 66 | String queryString = "SELECT ?mbox " + 67 | "WHERE { " + 68 | "?p 'Alice' ." + 69 | "?p ?mbox ." + 70 | "}"; 71 | // 直接通过QueryExecutionFactory来完成解析,并且获取执行器 72 | try (QueryExecution qexec = QueryExecutionFactory.create(queryString, model)) { 73 | // 获取查询之后的结果 74 | ResultSet results = qexec.execSelect(); 75 | 76 | // 遍历结果,进行处理 77 | for(; results.hasNext() ; ) { 78 | // 获取每一条查询结果 79 | QuerySolution soln = results.nextSolution(); 80 | Resource r = soln.getResource("mbox"); 81 | // RDFNode x = soln.get("varName") 82 | // Literal l = soln.getLiteral("varL") 83 | System.out.println("查询结果为:" + r.toString()); 84 | } 85 | } 86 | } 87 | 88 | public static void main(String []args) { 89 | System.out.println("------完整的查询流程---------"); 90 | query(); 91 | System.out.println("------简化的查询流程---------"); 92 | simplifyQuery(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /tdb/TDBDatasetExample.java: -------------------------------------------------------------------------------- 1 | package tdb; 2 | 3 | import org.apache.jena.query.Dataset; 4 | import org.apache.jena.query.ReadWrite; 5 | import org.apache.jena.rdf.model.Model; 6 | import org.apache.jena.rdf.model.Property; 7 | import org.apache.jena.sparql.core.DatasetGraph; 8 | import org.apache.jena.tdb.TDB; 9 | import org.apache.jena.tdb.TDBFactory; 10 | import org.apache.jena.tdb.TDBLoader; 11 | import org.apache.jena.tdb.store.DatasetGraphTDB; 12 | import org.apache.jena.vocabulary.RDFS; 13 | 14 | /** 15 | *创建、加载TDB数据库、TDB的 16 | * 17 | * (TDB是内存数据库,实际上就是把数据集加载到内存,然后进行操作) 18 | * 19 | * 构建TDB数据集,主要是通过类TDBFactory的createDataset方法, 20 | * 这个方法可以有两个参数: 21 | * 22 | * 1. 目录名称,存储数据集和一些辅助信息文件 23 | * 2. 给一个assembler文件,类似于配置文件,文件中存储数据集的相关信息 24 | * 25 | * 26 | * 27 | */ 28 | 29 | public class TDBDatasetExample { 30 | // 需要在根目录下,创建一个目录dataset,作为TDB数据存储的目录 31 | public static final String DIR = "dataset"; 32 | 33 | public static void write(Model model) { 34 | String NS = "urn:x-hp-jena:eg/"; 35 | Property p = model.createProperty(NS, "p"); 36 | Property q = model.createProperty(NS, "q"); 37 | model.add(p, RDFS.subPropertyOf, q); 38 | model.createResource(NS+"a").addProperty(p, "foo"); 39 | } 40 | 41 | /** 42 | * 写事务操作,在begin() - commit()之间,保证操作的原子性 43 | * 44 | * @param dataset 45 | */ 46 | 47 | public static void writeTransaction(Dataset dataset) { 48 | //进行数据集写操作,写入一些数据 49 | dataset.begin(ReadWrite.WRITE); 50 | try { 51 | // 获取数据集,此时数据集应该为空 52 | Model model = dataset.getDefaultModel(); 53 | // 为数据集添加数据 54 | write(model); 55 | // 提交数据,否则数据集的操作不会被提交 56 | dataset.commit(); 57 | } finally { 58 | dataset.end(); 59 | } 60 | } 61 | 62 | /** 63 | * 64 | * 读事务操作 65 | * 66 | * @param dataset 67 | */ 68 | 69 | public static void readTransaction(Dataset dataset) { 70 | // 读取数据 71 | dataset.begin(ReadWrite.READ); 72 | Model model = dataset.getDefaultModel(); 73 | model.write(System.out); 74 | dataset.end(); 75 | } 76 | 77 | /** 78 | * 通过目录名称构建TDB数据集 79 | * 80 | */ 81 | public static void constructingTDBDatasetByDir() { 82 | System.out.println("给定目录构建数据集..."); 83 | // 根据目录名称,创建数据集 84 | Dataset dataset = TDBFactory.createDataset(DIR); 85 | 86 | // 进行写事务操作 87 | writeTransaction(dataset); 88 | 89 | // 进行读操作 90 | readTransaction(dataset); 91 | 92 | // 保存到磁盘,避免缓存数据丢失 93 | TDB.sync(dataset); 94 | 95 | // 释放所有TDB占有的系统资源 96 | TDB.closedown(); 97 | } 98 | 99 | /** 100 | * 连接已有的TDB数据集,还是通过TDBFactory.createDataset() 101 | * 102 | */ 103 | public static void connect() { 104 | System.out.println("连接数据库..."); 105 | Dataset dataset = TDBFactory.createDataset(DIR); 106 | // 打印出数据集 107 | readTransaction(dataset); 108 | 109 | // 释放所有TDB占有的系统资源 110 | TDB.closedown(); 111 | } 112 | 113 | 114 | public static void main(String []args) { 115 | constructingTDBDatasetByDir(); 116 | connect(); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /inference/OWLReasonerExample.java: -------------------------------------------------------------------------------- 1 | package inference; 2 | 3 | import org.apache.jena.rdf.model.*; 4 | import org.apache.jena.reasoner.Reasoner; 5 | import org.apache.jena.reasoner.ReasonerRegistry; 6 | import org.apache.jena.reasoner.ValidityReport; 7 | import org.apache.jena.util.FileManager; 8 | import org.apache.jena.util.PrintUtil; 9 | import org.apache.jena.vocabulary.RDF; 10 | 11 | import java.util.Iterator; 12 | 13 | /** 14 | * owl reasoner的示例 15 | */ 16 | 17 | public class OWLReasonerExample { 18 | 19 | // 辅助函数,打印三元组 20 | public static void printStatements(Model m, Resource s, Property p, Resource o) { 21 | for(StmtIterator i = m.listStatements(s, p, o); i.hasNext(); ){ 22 | Statement stmt = i.nextStatement(); 23 | System.out.println("-" + PrintUtil.print(stmt)); 24 | } 25 | } 26 | 27 | public static void main(String []args) { 28 | // 加载预订好的模式(定义computer和computer的子类以及拥有的属性) 29 | // 可以将其视为本体库 30 | Model schema = FileManager.get().loadModel("data/owlDemoSchema.owl"); 31 | // 加载rdf数据 32 | Model data = FileManager.get().loadModel("data/owlDemoData.rdf"); 33 | 34 | // 获取推理器 35 | Reasoner reasoner = ReasonerRegistry.getOWLReasoner(); 36 | 37 | // 加入我们预先设置好的模式(本体库) 38 | reasoner = reasoner.bindSchema(schema); 39 | 40 | // 根据数据和reasoner,获取InfModel 41 | InfModel inf = ModelFactory.createInfModel(reasoner, data); 42 | 43 | // 进行推理查询 44 | 45 | /** 46 | * 示例1: SELECT * WHERE { ?nForce ?x ?y } 47 | * 查找nForce作为主体的所有三元组 48 | * 由于nForce是一种插件板(mother board),,插件板在schema中定义了 49 | * 若干种属性都会被打印出来。 50 | */ 51 | System.out.println("示例1: 属性推断"); 52 | Resource nForce = inf.getResource("urn:x-hp:eg/nForce"); 53 | System.out.println("nForce *:"); 54 | printStatements(inf, nForce, null, null); 55 | 56 | /** 57 | * 示例2:实例识别(instance recognition)。 58 | * whileBoxZx是一个Computer的实例,并且显示声明拥有gamebundle, 59 | * 还拥有nForce,因为nForce又有gamingGraphic组件 60 | * GamingComputer也是Computer的实例,并且拥有gamebundle和gamingGraphic 61 | * 因此,可以推断出whileBoxZx是GamingComputer的实例。 62 | */ 63 | System.out.println("示例2: 实例识别"); 64 | Resource gamingComputer = inf.getResource("urn:x-hp:eg/GamingComputer"); 65 | Resource whiteBox = inf.getResource("urn:x-hp:eg/whiteBoxZX"); 66 | if(inf.contains(whiteBox, RDF.type, gamingComputer)) { 67 | System.out.println("White box recognized as gaming computer"); 68 | } else { 69 | System.out.println("Failed to recognize white box correctly"); 70 | } 71 | 72 | /** 73 | * 示例3:检测逻辑一致性, 74 | * 在rdf数据中,bigName42既拥有插件板bigNameSpecialMB,有拥有nForce, 75 | * 违反了作为一个Computer只能拥有一个插件板的逻辑, 76 | */ 77 | System.out.println("示例2: 逻辑一致性检测"); 78 | ValidityReport validity = inf.validate(); 79 | if(validity.isValid()) { 80 | System.out.println("ok"); 81 | } else { 82 | System.out.println("Conflicts"); 83 | for(Iterator i = validity.getReports(); i.hasNext(); ) { 84 | ValidityReport.Report report = (ValidityReport.Report)i.next(); 85 | System.out.println(" - " + report); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /data/Creatrue.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix owl: . 3 | @prefix rdf: . 4 | @prefix xml: . 5 | @prefix xsd: . 6 | @prefix rdfs: . 7 | @base . 8 | 9 | rdf:type owl:Ontology . 10 | 11 | 12 | ################################################################# 13 | # 14 | # Object Properties 15 | # 16 | ################################################################# 17 | 18 | 19 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#is:a 20 | 21 | rdf:type owl:FunctionalProperty , 22 | owl:ObjectProperty . 23 | 24 | 25 | 26 | 27 | 28 | ################################################################# 29 | # 30 | # Classes 31 | # 32 | ################################################################# 33 | 34 | 35 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Animal 36 | 37 | :Animal rdf:type owl:Class ; 38 | 39 | rdfs:subClassOf :Createure . 40 | 41 | 42 | 43 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Branch 44 | 45 | :Branch rdf:type owl:Class ; 46 | 47 | rdfs:subClassOf :Tree . 48 | 49 | 50 | 51 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Createure 52 | 53 | :Createure rdf:type owl:Class . 54 | 55 | 56 | 57 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Grass 58 | 59 | :Grass rdf:type owl:Class ; 60 | 61 | rdfs:subClassOf :Plant . 62 | 63 | 64 | 65 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#GrassAnimal 66 | 67 | :GrassAnimal rdf:type owl:Class ; 68 | 69 | rdfs:subClassOf :Animal . 70 | 71 | 72 | 73 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Leaf 74 | 75 | :Leaf rdf:type owl:Class ; 76 | 77 | rdfs:subClassOf :Tree . 78 | 79 | 80 | 81 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#MeatAnimal 82 | 83 | :MeatAnimal rdf:type owl:Class ; 84 | 85 | rdfs:subClassOf :Animal . 86 | 87 | 88 | 89 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#MixeatAnimal 90 | 91 | :MixeatAnimal rdf:type owl:Class ; 92 | 93 | rdfs:subClassOf :Animal . 94 | 95 | 96 | 97 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Plant 98 | 99 | :Plant rdf:type owl:Class ; 100 | 101 | rdfs:subClassOf :Createure . 102 | 103 | 104 | 105 | ### http://www.semanticweb.org/zhang/ontologies/2016/10/untitled-ontology-6#Tree 106 | 107 | :Tree rdf:type owl:Class ; 108 | 109 | rdfs:subClassOf :Plant . 110 | 111 | 112 | 113 | 114 | ### Generated by the OWL API (version 3.5.0) http://owlapi.sourceforge.net 115 | 116 | -------------------------------------------------------------------------------- /notes/sparql/04SPARQL基础语法.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 4. SPARQL基础语法(Syntax) 8 | 9 | 本章节会介绍RDF术语和三元组模式的一些语法表示(跟turtle的语法有点类似)。 10 | 11 | ### 4.1 IRI 12 | 13 | IRI实际上是比URI更加一般化的概念,可以简单地理解为URI和URL。 14 | 15 | 关于IRI,知识点有: 16 | 17 | 1. 使用\来表示一个IRI 18 | 2. IRI有绝对IRI(irelative IRI)和相对IRI(relative IRI) 19 | 3. 前缀名(PrefixedName)可以表示一个IRI的地址前缀(也可以说是一个命名空间),这样可以相同的IRI前缀提取出来,减少一定数据量,也带来书写的方便。 20 | 4. BASE表示是当前文件中使用的IRI的基本路径,它的作用跟前缀名类似,在语法上有点不同。 21 | 22 | 举个例子,以下是一个IRI 23 | 24 | ``` 25 | 26 | ``` 27 | 28 | 我们可以通过前缀名和相对IRI来表示跟上面同一个IRI 29 | 30 | 1. 使用BASE 31 | 32 | ``` 33 | BASE 34 | 35 | ``` 36 | 37 | 2. 使用前缀名 38 | 39 | ``` 40 | PREFIX book: 41 | book:book1 42 | ``` 43 | 44 | ### 4.2 Literals 45 | 46 | Literal用于表示三元组中客体(Object),表示非IRI的数据,例如字符串(String),数字(xsd:integer),日期(xsd:date)等。 47 | 48 | 前面章节的例子可以看到,我们可以Literal中加入特殊的符号,来对数据进行进一步的约束和说明,在SPARQL中,literal的语法包括以下: 49 | 50 | 1. 普通字符串 51 | 52 | ``` 53 | "chat" 54 | ``` 55 | 56 | 2. 字符串中,使用`@+语言标签`来限定语言,例如例子中限定为法语 57 | 58 | ``` 59 | "chat"@fr 60 | ``` 61 | 62 | 3. 自定义类型,使用`^^`来指定定义类型的命名空间加以说明 63 | 64 | ``` 65 | "xyz"^^ 66 | "abc"^^appNS:appDataType 67 | ``` 68 | 69 | 4. 内置支持类型,在` `定义好了,在SPARQL可以直接使用(会自行进行匹配) 70 | 71 | ``` 72 | 1 (xsd:integer) 73 | 1.3 (xsd:decimal) 74 | 1.0e6 (xsd:double) 75 | true (xsd:boolean) 76 | ``` 77 | 78 | ### 4.3 查询变量表示 79 | 80 | 可以使用`?+string`或`$+string`来表示查询的变量,当然变量名有一些限制,具体可以[查看](https://www.w3.org/TR/sparql11-query/#rVARNAME) 81 | 82 | ### 4.4 空节点的语法表示 83 | 84 | 空节点的表示有两种 85 | 86 | * _:label 或者直接 :label,label仅仅在同一数据集有含义,标识一个空节点 87 | * [],当查询中只出现一次空节点时,就可以使用这种表示形式。 88 | 89 | *理解空节点语法的关键在于如何标识空节点,是否能与其他空节点区分开来* 90 | 91 | 此外,我们可以利用`[ predicate object ]`的语法形式来创建一个三元组模式,其中subject为一个空节点,里面的内容为谓词和客体。举个例子 92 | 93 | ``` 94 | [ 95 | foaf:name ?name ; 96 | foaf:mox . 97 | ] 98 | ``` 99 | 100 | 就相当于(假设我们创建的空白节点的标签为b18) 101 | 102 | ``` 103 | _:b18 foaf:name ?name . 104 | _:b18 foaf:mbox . 105 | ``` 106 | 107 | ### 4.5 三元组模式语法 108 | 109 | 三元组模式对应着RDF的三元组,只不是在主体、谓词、客体上可能是一个变量而已,它是用于匹配RDF数据的。 110 | 111 | *感觉全称可以叫做rdf匹配三元组* 112 | 113 | #### 4.5.1 谓词-客体列表(Predicate-Object Lists) 114 | 115 | 当都是同一个主体时,可以采用简写的方式,只要在每一个三元组模式列表项后面加上`;`,在最后一个三元组模式后面加上`.`来结束就可以。 116 | 117 | 例如 118 | 119 | ``` 120 | ?x foaf:name ?name ; 121 | foaf:mbox ?mbox . 122 | ``` 123 | 124 | 就相当于 125 | 126 | ``` 127 | ?x foaf:name ?name . 128 | ?x foaf:mbox ?mbox . 129 | ``` 130 | 131 | #### 4.5.2 客体列表(Object Lists) 132 | 133 | 我们可以通过`,`来表示多个客体。 134 | 135 | ``` 136 | ?x foaf:nick "Alice" , "Alice_" . 137 | ``` 138 | 139 | 相当于 140 | 141 | ``` 142 | ?x foaf:nick "Alice" . 143 | ?x foaf:nick "Alice_" . 144 | ``` 145 | 146 | Object List可以和Predicate-Object List结合使用。 147 | 148 | ``` 149 | ?x foaf:name ?name ; foaf:nick "Alice" , "Alice_" . 150 | ``` 151 | 152 | #### 4.5.3 RDF集合 153 | 154 | 我们可以使用`(e1 e2 ...)`在三元组模式中表示一个RDF集合。当使用集合元素时,会为其生成空节点,将各个元素串联起来。例如 155 | 156 | ``` 157 | (1 ?x 3 4) foaf:name "zhang" . 158 | ``` 159 | 160 | 其实是以下代码的语法糖: 161 | 162 | ``` 163 | _:b0 rdf:first 1 ; 164 | rdf:rest _:b2 . 165 | 166 | _:b1 rdf:first ?x ; 167 | rdf:rest _:b2 . 168 | 169 | _:b2 rdf:first 3 ; 170 | rdf:rest _:b3 . 171 | 172 | _:b3 rdf:first 4 ; 173 | rdf:rest rdf:nil . 174 | 175 | _:b0 foaf:name "zhang" . 176 | ``` 177 | 178 | *空节点是不会用于查询的* 179 | 180 | RDF集合还支持嵌套,和其他语法混合,例如 181 | 182 | ``` 183 | (1 [ foaf:name "zhang" ] (2)) . 184 | ``` 185 | 186 | 相当于 187 | 188 | ``` 189 | _:b0 rdf:first 1 ; 190 | rdf:rest _:b1 . 191 | 192 | _:b1 rdf:first _:b2 ; 193 | rdf:rest _:b3 . 194 | _:b2 foaf:name "zhang" . 195 | 196 | _:b3 rdf:first _:b4 ; 197 | rdf:rest rdf:nil . 198 | _:b4 rdf:first 2 ; 199 | rdf:rest rdf:nil . 200 | ``` 201 | 202 | #### 4.5.4 rdf:type 203 | 204 | 在SPARQL中,rdf:type可以简写成`a`,在三元组模式中作为谓词使用,代表IRI(http://www.w3.org/1999/02/22-rdf-syntax-ns#type),举个例子 205 | 206 | ``` 207 | ?x a :Class1 . 208 | ``` 209 | 210 | 相当于 211 | 212 | ``` 213 | ?x rdf:type :Class1 . 214 | ``` 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /notes/semantic/owl.md: -------------------------------------------------------------------------------- 1 | # OWL简介 2 | 3 | [owl官方标准文档](https://www.w3.org/TR/2004/REC-owl-features-20040210/) 4 | 5 | ## 1. 本体 6 | 7 | `本体(notes.ontology)`指的就是概念和概念之间的关系。本体的目标是获取相关的领域知识,提供对该领域知识的共同理解,确定该领域内共同认可的词汇,并从不同层次的形式化模式上给出这些词汇(术语)和词汇间相互关系的明确定义。 8 | 9 | ## 2. 本体语言OWL 10 | 11 | 12 | 13 | ### 2.1 OWL的子语言 14 | 15 | OWL提供三种子语言(语言表达能力逐渐增强): 16 | 17 | * OWL Lite从 语法上来说,OWL-Lite是三个之中最简单的一个,当你的本体中类的层次结构很简单,并且只有简单的约束(constraint)时适合使用它来描述本体 18 | * OWL DL 和 OWL-Lite相比,OWL-DL的表达能力要丰富许多,它的基础是描述逻辑(Description Logics,即DL的由来)。描述逻辑是一阶逻辑(First Order Logic)的一个可判定的变种(译注:不一定准确,原文decidable fragment),因此可以用来进行自动推理,计算机从而可以知道本体中的分类层次,以及本体中的各种概念是否一致 19 | * OWL Full是OWL的三种子语言中表达能力最强的一个,适合在那些需要非常强的表达能力,而不用太关心可判定性(decidability)或是计算完全性的场合下使用。不过也正是由于表达能力太强这个原因,用OWL-Full表示的本体是不能进行自动推理的。 20 | 21 | 这三种子语言是包含关系,分别是OWL Full>OWL DL>OWL Lite,OWL Full是最大的集合。 22 | 23 | ### 2.2 OWL基础词汇 24 | 25 | 在OWL中,包含着一些基础的词汇,这些在构建本体的时候非常有用。 26 | 27 | |词汇|作用| 28 | |:--|:--| 29 | |owl:Ontology|声明一个本体| 30 | |owl:Class|定义一个类| 31 | |rdfs:subClassOf|定义一个类的子类| 32 | |owl:Thing|内置的类,作为所有类的父类| 33 | |owl:ObjectProperty|定义对象属性| 34 | |rdfs:domain|定义属性的定义域| 35 | |owl:DatatypeProperty|定义数值类型的属性| 36 | |rdfs:range|定义属性的值域| 37 | |owl:FunctionalProperty|定义函数类型的属性| 38 | |owl:inverseOf|表示两个属性是互逆| 39 | |rdfs:ID|定义所描述概念的名称| 40 | 41 | ### 2.3 OWL Lite纲要 42 | 43 | OWL Lite主要包含以下关系描述: 44 | 45 | ![owl lite](../../images/owl-01.png) 46 | 47 | 可以看到这些关系术语都是很贴近计算机编程的,例如类、属性、数据类型等等。 48 | 49 | ### 2.4 OWL DL和OWL Full纲要 50 | 51 | ![owl dl & owl](../../images/owl-02.png) 52 | 53 | ## 3. OWL Lite的术语描述 54 | 55 | 简介关系描述的具体含义 56 | 57 | TBD). 58 | 59 | ## 4. 本体描述文件 60 | 61 | [owl guide](https://www.w3.org/TR/owl-guide/) 62 | 63 | ### 2.1 命名空间(Namespace) 64 | 65 | 在我们使用术语之前,我们需要通过命名空间来指定本体使用了哪些词汇。一个典型的本体描述文件都会以命名空间声明开头。 66 | 67 | ```xml 68 | 77 | 78 | ``` 79 | 80 | 属性值不具有命名空间,在OWL里可以写出它们的完整URI,完整的URI可以利用实体定义来简略。 81 | 82 | ```xml 83 | 85 | ]> 86 | ``` 87 | 88 | 上面的命名空间就可以简写成为: 89 | 90 | ```xml 91 | 100 | 101 | ``` 102 | 103 | ### 2.2 本体头部 104 | 105 | 在`owl:Ontology`标签中给出本体的声明。来看一个例子: 106 | 107 | ```xml 108 | 109 | An example OWL ontology 110 | 111 | 112 | Wine Ontology 113 | 114 | ``` 115 | 116 | 其中 117 | 118 | * `owl:Ontology`标签内收集了文档的OWL元数据。 119 | * `rdf:about`属性为本体提供一个名称或引用。当值为""时,表示本体的名称为base URI。 120 | * `rdfs:comment`用于描述本体。 121 | * `owl:priorVersion`为本体版本控制提供相关信息的标准标签。 122 | * `owl:imports`提供一种嵌入机制,接受一个用`rdf:resource`属性标识的参数。 123 | 124 | ## 3. 基本元素 125 | 126 | 大多数OWL本体的元素都是关于 127 | 128 | * classes 129 | * properties 130 | * instances of classes 131 | * relationships between instances 132 | 133 | ### 3.1 简单的类(Classes)和个体(Individuals) 134 | 135 | `extension(外延)`:属于某个类的个体所构成的集合为该类的外延。 136 | 137 | 138 | #### 3.1.1 简单的命名类 139 | 140 | 一个领域中最基本的概念对应各个分类层次树的根。 141 | 142 | 在OWL中,每一个个体都是类`owl:Thing`的成员(基类,类似于Java中的Object)。因此每个自定义的类都是`owl:Thing`的子类。 143 | 144 | 在OWL中,可以通过`owl:Nothing`来定义一个空的类。 145 | 146 | 特定领域的根类可以通过声明一个命名类来定义。 147 | 148 | ```xml 149 | 150 | 151 | 152 | ``` 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /notes/fuseki.md: -------------------------------------------------------------------------------- 1 | # Fuseki 2 | 3 | ## 1. 简介 4 | 5 | Fuseki是一个HTTP服务器,它主要的作用有 6 | 7 | 1. 在HTTP的基础上实现了SPARQL通信协议,提供SPARQL的查询远程web服务 8 | 2. 内置TDB,可以使用TDB来执行SPARQL查询,获取rdf数据。 9 | 10 | ## 2. 运行Fuseki 11 | 12 | 首先要先下载[Fuseki](http://jena.apache.org/download/#apache-jena-fuseki) 13 | 14 | 然后进行解压,解压之后,文件如下(fuseki v2) 15 | 16 | ![fuseki-catelog.png](../images/fuseki-catelog.png) 17 | 18 | [英文文档地址](http://jena.apache.org/documentation/fuseki2/fuseki-run.html) 19 | 20 | ### 2.1 命令行运行 21 | 22 | 在window下,使用命令行运行,只要依赖于两个文件 23 | 24 | 1. fuseki-server.bat 25 | 2. fuseki-server.jar 26 | 27 | 配置环境的大致步骤为: 28 | 29 | 1. 将解压后的文件夹路径拷贝,例如d:\\fuseki 30 | 2. 配置环境变量,新建一个FUSEKI_HOME = d:\\fuseki 31 | 3. 将FUSEKI_HOME添加到PATH的末尾,PATH = ....;%FUSEKI_HOME% 32 | 4. 需要在有fuseki-server.jar包的目录下运行(尝试配置了CLASSPATH,但是还是无法运行,会报`Can't find jarfile to run`) 33 | 34 | 之后,就可以在cmd中,直接运行 35 | 36 | ```shell 37 | fuseki-server 38 | ``` 39 | 40 | 运行之后会在当前目录下创建一个run(FUSEKI_BASE)的文件夹,用于保存运行的实例的各种信息,此外,还可以通过`FUSEKI_BASE/configuration`来配置数据服务。(data service) 41 | 42 | 在浏览器中输入`localhost:3030`,就可以看到一个配置的页面, 43 | 44 | ![fuseki-server-ui.png](../images/fuseki-server-ui.png) 45 | 46 | 此时,我们需要给其配置一个数据集,才能有进一步的操作, 47 | 48 | ![fuseki-create-database.png](../images/fuseki-create-database.png) 49 | 50 | 我们给新建的数据库导入一些数据 51 | 52 | ![fuseki-database-upload.png](../images/fuseki-database-upload.png) 53 | 54 | 根据提示,可以看到可以上传rdf格式的文件作为数据,我们选择了[data/example.rdf](../data/example.rdf)作为数据上传 55 | 56 | ![fuseki-upload-files.png](../images/fuseki-upload-files.png) 57 | 58 | 上传成功后,我们可以在页面上进行查询 59 | 60 | ![fuseki-query.png](../images/fuseki-query.png) 61 | 62 | ### 2.2 以Web应用程序的形式运行 63 | 64 | 解压的文件中,还提供了一个war包,这就意味着我们可以直接使用tomcat来运行fuseki。因为Fuseki中要求至少支持Servlet 3.0 API,因此至少要求tomcat版本为7或者Jetty 8,并且java 8。 65 | 66 | 如果在linux下,FUSEKI_BASE默认为/etc/fuseki,需要为这个文件赋予写的权限。 67 | 68 | ### 2.3 以服务的形式运行 69 | 70 | Fuseki可以作为操作系统的一个服务来运行,并且设置开机启动,在解压的文件中有一个fuseki的搅拌,它其实是一个linux的init.d,可以将fuseki配置到开机启动中。 71 | 72 | 运行时,进程的参数会从`/etc/default/fuseki`包括`FUSEKI_HOME`和`FUSEKI_BASE`中读取。 73 | 74 | ## 3. SOH(SPARQL over HTTP) 75 | 76 | 从解压的文件中,在bin目录下,还提供了 77 | 78 | ![soh-scripts](../images/soh-scripts.png) 79 | 80 | 这些其实就是SOH(SPARQL over HTTP)的命令行工具,我们可以通过这些命令行工具来进行SPARQL的查询,通信是基于HTTP协议。 81 | 82 | [英文文档SOH](http://jena.apache.org/documentation/fuseki2/soh.html) 83 | 84 | 由于这些脚本都是采用ruby编写的,因此必须在电脑上先安装ruby,然后配置环境变量,使其能够在cmd中直接运行ruby命令。 85 | 86 | 来个示例,首先,我们先启动fuseki 87 | 88 | ![fuseki-database-test.png](../images/fuseki-database-test.png) 89 | 90 | 可以看到我们在上一节配置的数据集test。 91 | 92 | ### 3.1 直接查询 93 | 94 | ```shell 95 | ruby s-query --service=endpointURL 'query string' 96 | ruby s-query --server=endpointURL --query=queryFile.rq 97 | ``` 98 | 99 | 在上面搭建的环境下,endpointURL可以在query的页面上查询到,即 100 | 101 | ![s-query-endpointURL.png](../images/s-query-endpointURL.png) 102 | 103 | 我们需要切换到bin目录下,在该目录下,我们新建一个query的脚本文件`testquery.rq`,内容为: 104 | 105 | ```sql 106 | PREFIX rdf: 107 | SELECT ?subject ?predicate 108 | WHERE { 109 | ?subject ?predicate "John Smith" 110 | } 111 | LIMIT 25 112 | ``` 113 | 114 | 然后执行脚本 115 | 116 | ```shell 117 | ruby s-query --server=http://localhost:3030/test/query --query=testquery.rq 118 | ``` 119 | 120 | 执行结果为(返回的是json数据) 121 | 122 | ![s-query-result.png](../images/s-query-result.png) 123 | 124 | ### 3.2 简易的http操作命令 125 | 126 | 在这里必须介绍一下[SPARQL Graph Store Protocol](https://www.w3.org/TR/sparql11-http-rdf-update/#introduction)这个协议,大致就是通过HTTP头部的操作方法来对RDF的数据模型进行更新操作,示意图如下: 127 | 128 | ![RDF-graph-protocol-model](../images/RDF-graph-protocol-model.jpg) 129 | 130 | SOH同样提供了脚本,使其能够便捷地对数据模型进行更新,有 131 | 132 | * s-get 133 | * s-post 134 | * s-put 135 | * s-delete 136 | 137 | 脚本语法为(在window环境下同样要加ruby) 138 | 139 | ```shell 140 | s-VERB databaseURI grapName [file] 141 | ``` 142 | 143 | 在fuseki的UI页面对应地有`edit`,可以对模型进行操作 144 | 145 | ![fuseki-edit.png](../images/fuseki-edit.png) 146 | 147 | 需要注意的是,语法中的`databaseURI`对应的操作有不同的URI,可以在页面中的`info`栏下查看到: 148 | 149 | ![fuseki-info.png](../images/fuseki-info.png) 150 | 151 | 我们直接在命令行对其进行操作(示例), 152 | 153 | ```shell 154 | # 获取rdf graph 155 | ruby s-get http://localhost:3030/test/get default > graph 156 | ``` 157 | 158 | 打开graph文件,内容与edit页面的编辑框的内容是一致,同为 159 | 160 | ![s-get-graph.png](../images/s-get-graph.png) 161 | 162 | ### 3.3 update操作 163 | 164 | 我们可以在edit页面上直接编辑操作,也可以使用`s-upadte`来对数据进行更新操作 165 | 166 | ```shell 167 | s-update --service=endpointURL 'update string' 168 | s-update --service=endpointURL --update=updateFile.ru 169 | ``` 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /notes/semantic/rdf.md: -------------------------------------------------------------------------------- 1 | # RDF 2 | 3 | ## 1. 基本概念 4 | 5 | RDF(Resource Definition Framework),资源描述框架,是用于描述网络资源的W3C的标准。它被设计为可被计算机阅读和理解,是W3C的语义网技术的重要的组成部分。 6 | 7 | ### 1.1 三元组(Triples) 8 | 9 | RDF采用三元组(Triple)集合的形式构建Web数据的语义描述模型,就像自然语言中的一个语句,一个三元组包括: 10 | 11 | 1. 主体(subject) 12 | 2. 谓词(predicate) 13 | 3. 客体(object) 14 | 15 | 主体、谓词和客体都采用统一资源描述符(Uniform Resource Identifier, URI)标识。URI标识了Web上唯一的一个资源,并且通过链接引用资源,从而保证RDF中的概念不仅仅是文字,还可以在Web上找到定义描述信息。 16 | 17 | ### 1.2 RDF Graph(RDF图) 18 | 19 | 一个三元组形式的语句就表示一条RDF数据,即有等式 20 | 21 | Triples = statement = subject + predicate + object 22 | 23 | 相同的资源可以在一个三元组中处于主体位置,在另一个中处于客体位置,这就有可能找到三元组间的连接。三元组集合之间的相互连接,就形成了所谓的RDF图(RDF Graph)。每一个RDF图是一个处理元数据的数学模型。元数据,就是“描述数据的数据”或者“描述信息的信息”。 24 | 25 | 在一个RDF图(见RDF表示), 26 | 27 | 1. 节点:主体\客体 28 | 2. 弧:谓词 29 | 30 | ![rdf-graph.jpg](../../images/rdf-graph.jpg) 31 | 32 | ## 2. RDF的数据模型 33 | 34 | 为了构建RDF的三元组或者RDF图(两者只是角度不同,含义是一样的),常见的RDF数据模型有以下几种。(会在Jena框架中找到对应的类与之对应) 35 | 36 | ### 2.1 Resource(资源) 37 | 38 | RDF描述的各种事物都称作资源。一个资源可以是一个网页,或者是网页的一部分的HTML文档,或者是一个网页的集合。在资源中,我们通过使用IRI(International Resource Identifier)来标识一个资源,可以在三元组的任意位置。 39 | 40 | ### 2.2 Literal 41 | 42 | 三元组中的客体的位置可以是Resource,也可以是一个Literal,即 43 | 44 | * 字符串 45 | * 日期 46 | * 数值 47 | * XML Schema定义的数据类型 48 | 49 | ### 2.3 Property 50 | 51 | 属性是资源的一个特定方面、特征或者用来描述资源间的关系。每个属性都有一个特定的意义,用来说明这个属性能够描述的资源类型和这个属性与别的属性间的关系。 52 | 53 | ### 2.2 Statement(RDF陈述) 54 | 55 | Statement用于表示一条完整的三元组数据可以表示为一个RDF陈述,例如以下一个RDF三元组数据: 56 | 57 | * 主体(Subject)是:http://www.phpStudy.net/rdf 58 | * 谓语(Predicate)是:author 59 | * 客体(Object)是:Zhang 60 | 61 | 表示为RDF陈述:"The author of http://www.phpStudy.net/rdf is Zhang", 62 | 63 | ### 2.5 Blank Node(空节点) 64 | 65 | 用于表示无需使用IRI明确标识的资源,可以出现在主体和客体位置。 66 | 67 | ### 2.6 Graph(图) 68 | 69 | 一个RDF数据集中,至少有一个未命名的图(Default graph),可以有多个命名图(Named Graph),RDF数据的可以指定一个图进行查询,也可以在多个图进行联合查询(Union Graph)。 70 | 71 | ### 2.7 RDF Vocabularies(RDF词表) 72 | 73 | RDF词表是使用RDFS语言定义了RDF三元组中之间客体和主体之间的属性关系的词汇表,包括 74 | 75 | * 关系 76 | * 类别(类和子类、属性和子属性) 77 | * 限制(领域和范围) 78 | 79 | 之所以要使用词汇表是因为词表可以被重用,而且被重用越多,词汇表的意义更大。 80 | 81 | ## 3. RDF表示 82 | 83 | ### 3.1 N-Triples 84 | 85 | 常用于交换大量的RDF,以及面向行的文本处理工具处理大的RDF图,每行代表一个三元组,用尖括号封闭完整的IRI,句点表示三元组结束。 86 | 87 | ``` 88 | 89 | ``` 90 | 91 | ### 3.2 Turtle 92 | 93 | 支持命名空间前缀、列表和数据类型串的速写,如 94 | 95 | ``` 96 | @base 97 | @prefix foaf: 98 | @prefix rdfs: 99 | a foaf:Person . 100 | ``` 101 | 102 | 其中 103 | 104 | 1. `base`提供IRI缩写,基于IRI,例如``就是相对的IRI,要根据`base`来进行解析。 105 | 2. `prefix`则是定义一个命名空间前缀。 106 | 3. `a foaf:Person`中,谓词a是属性`rdf:type`的速写,表示实例关系。 107 | 108 | *文件后缀为ttl* 109 | 110 | ### 3.3 TriG(Turtle的扩展) 111 | 112 | 每个图中的三元组用花括号括起来,其他的句法与Turtle一直,关键词`Graph`可选,可以提高可读性。 113 | 114 | ``` 115 | Graph 116 | @base 117 | @prefix foaf: 118 | @prefix rdfs: 119 | { 120 | a foaf:Person 121 | } 122 | ``` 123 | 124 | ### 3.4 N-Quads(四元组) 125 | 126 | N-Triples的多图扩展,四元组,在一行中加入第4个元素,捕捉该行描述三元组的图IRI,如 127 | 128 | ``` 129 | 130 | ``` 131 | 132 | ### 3.5 JSON-LD 133 | 134 | 我们知道在web中使用JSON数据传输数据可以大大缩写数据传输的体积。为了方便在Web中通信,RDF数据可以使用JSON-LD的形式来标识。它是基于json的RDF句法,以最小的变化来实现RDF数据和JSON文档之间的相互转换,例如: 135 | 136 | ```ttl 137 | @base 138 | @prefix foaf: 139 | @prefix rdfs: 140 | a foaf:Person . 141 | ``` 142 | 143 | 使用sparql命令行工具可以转换为JSON数据: 144 | 145 | 146 | ```json 147 | { 148 | "head": { 149 | "vars": [ "o" , "p" , "s" ] 150 | } , 151 | "results": { 152 | "bindings": [ 153 | { 154 | "x": { "type": "uri" , "value": "http://example.org/bob#me" } , 155 | "y": { "type": "uri" , "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , 156 | "z": { "type": "uri" , "value": "http://xmlns.com/foaf/0.1/Person" } 157 | } 158 | ] 159 | } 160 | } 161 | ``` 162 | 163 | ### 3.6 RDF/XML形式 164 | 165 | RDF使用XML编写,通过XML,RDF信息可以轻易地在使用不同类型的操作系统和应用程序的计算机之间进行交换。如下,一个简单的rdf文件内容示例。 166 | 167 | ![rdf-example](../../images/rdf-example.png) 168 | 169 | 本图是有W3C的一个在线工具[Validator](http://www.w3.org/RDF/Validator/)生成的。 170 | 171 | ## 4. RDF数据的查询 172 | 173 | 目前无论是研究还是工程,都是以W3C的推出的SPARQL标准作为RDF数据的查询语言。 174 | 175 | [SPARQL]() 176 | 177 | ## 5. RDF数据的存储 178 | 179 | * 有基于关系型数据库的存储方案 180 | * 有基于NoSQL的存储方案 181 | * 有Native RDF database,即原生支持存储三元组的RDF数据库,例如Jena中的TDB就是。 -------------------------------------------------------------------------------- /notes/sparql/02查询入门.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 2. 入门(简单示例) 8 | 9 | 在绝多数`SPARQL`查询语句中都包含一系列的三元组(匹配)模式,这些被叫做基本图匹配模式(basis graph pattern)。三元组模式跟RDF的三元组很类似,不同的是,在三元组模式中,主体、谓词、客体都有可能是一个变量。一个基本的图模式会去匹配RDF数据的子图。 10 | 11 | ### 2.1 简单的查询示例 12 | 13 | 示例,有以下数据: 14 | 15 | ``` 16 | "SPARQL Tutorial" . 17 | ``` 18 | 19 | 查询语句 20 | 21 | ``` 22 | SELECT ?title 23 | WHERE 24 | { 25 | ?title . 26 | } 27 | ``` 28 | 29 | 查询结果为: 30 | 31 | ![sparql-example-01.png](../../images/sparql-example-01.png) 32 | 33 | ## 2.2 多重匹配查询 34 | 35 | 我们根据查询条件,对数据进行序列处理(solution sequence,在后面还有更加详尽的解释),匹配出所符合条件的数据。 36 | 37 | ``` 38 | @prefix foaf: . 39 | 40 | _:a foaf:name "Johnny Lee Outlaw" . 41 | _:a foaf:mbox . 42 | _:b foaf:name "Peter Goodguy" . 43 | _:b foaf:mbox . 44 | _:c foaf:mbox . 45 | ``` 46 | 47 | 查询语句 48 | 49 | ``` 50 | PREFIX foaf: 51 | SELECT ?name ?mbox 52 | WHERE 53 | { 54 | ?x foaf:name ?name . 55 | ?x foaf:mbox ?mbox . 56 | } 57 | ``` 58 | 59 | 按照本人的理解,应该就是先按照条件匹配`?x foaf:name ?name`,然后在匹配其中有`?x foaf:mbox ?mbox`,这样一个顺序,最后查询出符合条件的所有结果。 60 | 61 | ![sparql-example-02.png](../../images/sparql-example-02.png) 62 | 63 | ### 2.3 匹配RDF Literals 64 | 65 | 这就是匹配客体上的字符串数据,有示例数据 66 | 67 | ``` 68 | @prefix dt: . 69 | @prefix ns: . 70 | @prefix : . 71 | @prefix xsd: . 72 | 73 | :x ns:p "cat"@en . 74 | :y ns:p "42"^^xsd:integer . 75 | :z ns:p "abc"^^dt:specialDatatype . 76 | ``` 77 | 78 | #### 2.3.1 通过语言来匹配 79 | 80 | 在查询语句中,可以使用`@+语言标签`指定语言,[语言标签](http://www.rfc-editor.org/rfc/bcp/bcp47.txt),例如在示例数据中,就使用`@en`来指定`cat`为英文。在查询时,如果不加上`cat@en`,以下查询是没有结果的。 81 | 82 | ``` 83 | SELECT ?v 84 | WHERE 85 | { 86 | ?v ?p "cat" 87 | } 88 | ``` 89 | 90 | ![sparql-example-03.png](../../images/sparql-example-03.png) 91 | 92 | 必须修改为 93 | 94 | ``` 95 | SELECT ?v 96 | WHERE 97 | { 98 | ?v ?p "cat"@en 99 | } 100 | ``` 101 | 102 | ![sparql-example-04.png](../../images/sparql-example-04.png) 103 | 104 | #### 2.3.2 匹配数字类型 105 | 106 | 在查询中,已经默认了数字类型为`xsd:`定义的数字类型,有 107 | 108 | * xsd:integer 109 | * xsd:float 110 | * xsd:double 111 | 112 | ``` 113 | SELECT ?v 114 | WHERE 115 | { 116 | ?v ?p 42 117 | } 118 | ``` 119 | 120 | 查询结果为 121 | 122 | ![sparql-example-05.png](../../images/sparql-example-05.png) 123 | 124 | #### 2.3.3 匹配自定义类型 125 | 126 | 如果需要匹配自定义类型,那么就需要在查询的时候加入自定义类型的定义,例如在示例数据中查询`z`的数据,就必须跟上自定义类型的定义空间。 127 | 128 | ``` 129 | SELECT ?v 130 | WHERE 131 | { 132 | ?v ?p "abc"^^ . 133 | } 134 | ``` 135 | 136 | ![sparql-example-06.png](../../images/sparql-example-06.png) 137 | 138 | 139 | ### 2.4 空节点 140 | 141 | 查询的结果是可以包含空节点的。在示例的数据中,空节点即`_:`,也可以什么都不写,就只有一个`:`,后面跟着的`a`或`b`则是空节点的标签。需要注意的是空节点的标签并`没有具体的含义`,只是拿来区别两个空节点而已,可以任意修改。 142 | 143 | ``` 144 | @prefix foaf: . 145 | 146 | _:a foaf:name "Alice" . 147 | _:b foaf:name "Bob" . 148 | ``` 149 | 150 | 空节点标签会被包括在返回的结果中,在一个结果集里面,使用相同的空节点标签代表同一个空白节点。(在不同结果集里面,则是没有任何联系的) 151 | 152 | 例如我们对数据进行查询, 153 | 154 | ``` 155 | PREFIX foaf: 156 | SELECT ?x ?name 157 | WHERE 158 | { 159 | ?x foaf:name ?name . 160 | } 161 | ``` 162 | 163 | ![sparql-example-07.png](../../images/sparql-example-07.png) 164 | 165 | *由于标签是没有含义的,仅仅作为标识使用,因此标签不能作为查询中的条件来使用* 166 | 167 | ### 2.5 表达式创建值(Creating Values with Expressions) 168 | 169 | 在SPARQL中,允许我们通过复杂的表示式来创建值。 170 | 171 | 这里的`表达式(Expression)`可以说是内置的函数,例如`CONCAT`函数等,[表示式列表](https://www.w3.org/TR/sparql11-query/#selectExpressions) 172 | 173 | 我们通过一个示例来看如何在SELECT中运用表达式。 174 | 175 | ``` 176 | @prefix foaf: . 177 | 178 | _:a foaf:givenName "John" . 179 | _:a foaf:surname "Doe" . 180 | ``` 181 | 182 | 我们通过查询,将结果合成一个完整的姓名返回。 183 | 184 | ``` 185 | PREFIX foaf: 186 | SELECT ?name 187 | WHERE 188 | { 189 | ?x foaf:givenName ?G ; 190 | foaf:surname ?S . 191 | BIND(CONCAT(?G, " ", ?S) AS ?name) 192 | } 193 | ``` 194 | 195 | ![sparql-example-08.png](../../images/sparql-example-08.png) 196 | 197 | ### 2.6 (查询结果)建立RDF图(RDF Graphs) 198 | 199 | 在SPARQL中,CONSTRUCT查询可以返回一个rdf图。这个图是基于生成RDF三元组的模版和查询匹配结果进行建立的。 200 | 201 | *SELECT查询返回的变量绑定(variable bindings)。只能意会一下了。* 202 | 203 | 示例: 204 | 205 | ``` 206 | @prefix org: . 207 | 208 | _:a org:employeeName "Alice" . 209 | _:a org:employeeId 12345 . 210 | 211 | _:b org:employeeName "Bob" . 212 | _:b org:employeeId 67890 . 213 | ``` 214 | 215 | 查询语句 216 | 217 | ``` 218 | PREFIX org: 219 | PREFIX foaf: 220 | 221 | CONSTRUCT { 222 | ?x foaf:name ?name 223 | } WHERE { 224 | ?x org:employeeName ?name 225 | } 226 | ``` 227 | 228 | ![sparql-example-09.png](../../images/sparql-example-09.png) 229 | 230 | 这个结果可以被序列化为RDF/XML文件,我们通过加一个参数来`--result=RDF`来将查询结果序列化成rdf graph。 231 | 232 | ![sparql-example-10.png](../../images/sparql-example-10.png) -------------------------------------------------------------------------------- /notes/sparql/05图模式.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 5. 图模式(Graph Pattern) 8 | 9 | SPARQL是基于图模式匹配的,更多复杂的图模式可以通过结合更小的模式来组合而成。 10 | 11 | * 基础图模式(Basis Graph Pattern):必须匹配给出所有三元组 12 | * 组图模式(Group Graph Pattern):必须匹配给出所有图模式 13 | * 可选图模式(Optional Graph Pattern):可以通过附加的模式来扩展匹配结果 14 | * 可替代图模式(Alternative Graph Pattern):尝试至少两个可能的模式进行匹配 15 | * 命名图模式(Patterns on Named Graphs):在非命名图中匹配模式 16 | 17 | ### 5.1 基础图模式 18 | 19 | 基础的图模式的组成有两部分: 20 | 21 | * 一系列的三元组模式 22 | * 附加的filter 23 | 24 | SPARQL通过子图匹配来计算基本图模式,子图匹配的机制使用的预定义好的,[定义的文档](http://www.w3.org/TR/sparql11-entailment/),匹配机制可以被扩展。 25 | 26 | ### 5.2 组图模式 27 | 28 | 在一个SPARQL语句查询中,一组图模式使用`{}`进行包裹,例如 29 | 30 | ``` 31 | PREFIX foaf: 32 | SELECT ?name ?mbox 33 | WHERE { 34 | { 35 | ?x foaf:name ?name . 36 | } 37 | { 38 | ?x foaf:mbox ?mbox . 39 | } 40 | } 41 | ``` 42 | 43 | 示例代码中,就有一组图模式,由两个基础的图模式组成,两个基础的图模式中各有一个三元组模式。 44 | 45 | 在前几章中,我们的查询语句都是 46 | 47 | ``` 48 | PREFIX foaf: 49 | SELECT ?name ?mbox 50 | WHERE { 51 | ?x foaf:name ?name . 52 | ?x foaf:mbox ?mbox . 53 | } 54 | ``` 55 | 56 | 实际上查询的模式也是组图模式,只是这一组图模式中只包含了一个基本的图模式。 57 | 58 | #### 5.2.1 空组模式 59 | 60 | 一个空的组模式,其实就是 61 | 62 | ``` 63 | {} 64 | ``` 65 | 66 | #### 5.2.2 Filter作用范围 67 | 68 | 一个FILTER的作用范围为该FILTER出现的组图模式,即出现的那个`{}`。 69 | 70 | 例如,以下三种写法效果都是一样的。 71 | 72 | ``` 73 | // 写法1 74 | { ?x foaf:name ?name . 75 | ?x foaf:mbox ?mbox . 76 | FILTER regex(?name, "Smith") 77 | } 78 | 79 | // 写法2 80 | { FILTER regex(?name, "Smith") 81 | ?x foaf:name ?name . 82 | ?x foaf:mbox ?mbox . 83 | } 84 | 85 | // 写法3 86 | { ?x foaf:name ?name . 87 | FILTER regex(?name, "Smith") 88 | ?x foaf:mbox ?mbox . 89 | } 90 | ``` 91 | 92 | ### 5.3 可选模式匹配 93 | 94 | 在SPARQL查询中,可以通过`OPTIONAL`来添加可选的模式匹配,模式匹配在至少满足基本图模式的情况下,执行可选的模式匹配不会缩减满足基本图模式的结果集。 95 | 96 | 举个例子 97 | 98 | ``` 99 | @prefix foaf: . 100 | @prefix rdf: . 101 | 102 | _:a rdf:type foaf:Person . 103 | _:a foaf:name "Alice" . 104 | _:a foaf:mbox . 105 | _:a foaf:mbox . 106 | 107 | _:b rdf:type foaf:Person . 108 | _:b foaf:name "Bob" . 109 | ``` 110 | 111 | 在上面的数据中,我们查询拥有属性`foaf:name`的基础图模式,添加可选模式,如果在结果集还存在`foaf:mbox`属性的图模式,将其查找出来。 112 | 113 | ``` 114 | PREFIX foaf: 115 | SELECT ?name ?mbox 116 | WHERE { 117 | ?x foaf:name ?name . 118 | OPTIONAL { 119 | ?x foaf:mbox ?mbox 120 | } 121 | } 122 | ``` 123 | 124 | ![sparql-example-13.png](../../images/sparql-example-13.png) 125 | 126 | 从查询结果可以看到,因为`Bob`是没有`foaf:mbox`,因此`mbox`的值为空,但是并没有从结果集中被删除掉。 127 | 128 | #### 5.3.1 可选模式中使用Filter 129 | 130 | 在可选的模式中,也可以使用`FILTER`,举个就明白了。 131 | 132 | ``` 133 | @prefix dc: . 134 | @prefix : . 135 | @prefix ns: . 136 | 137 | :book1 dc:title "SPARQL Tutorial" . 138 | :book1 ns:price 42 . 139 | :book2 dc:title "The Semantic Web" . 140 | :book2 ns:price 23 . 141 | ``` 142 | 143 | ``` 144 | PREFIX dc: 145 | PREFIX ns: 146 | SELECT ?title ?price 147 | WHERE { 148 | ?x dc:title ?title . 149 | OPTIONAL { 150 | ?x ns:price ?price . 151 | FILTER (?price < 30) 152 | } 153 | } 154 | ``` 155 | 156 | ![sparql-example-14.png](../../images/sparql-example-14.png) 157 | 158 | #### 5.3.2 多重可选模式 159 | 160 | 在SPARQL查询语句中,可以声明多个`OPTIONAL`。举个例子 161 | 162 | ``` 163 | @prefix foaf: . 164 | 165 | _:a foaf:name "Alice" . 166 | _:a foaf:homepage . 167 | 168 | _:b foaf:name "Bob" . 169 | _:b foaf:mbox . 170 | ``` 171 | 172 | ``` 173 | PREFIX foaf: 174 | SELECT ?name ?mbox ?hpage 175 | WHERE { 176 | ?x foaf:name ?name . 177 | OPTIONAL { 178 | ?x foaf:mbox ?mbox . 179 | } 180 | OPTIONAL { 181 | ?x foaf:homepage ?hpage . 182 | } 183 | } 184 | ``` 185 | 186 | ![sparql-example-15.png](../../images/sparql-example-15.png) 187 | 188 | ### 5.4 可替代模式匹配 189 | 190 | SPARQL提供了一种组合多个图模式的方式,只要满足多个图模式的其中之一即可组成结果集。 191 | 192 | 使用`UNION`来完成这种匹配模式,下面举个例子。 193 | 194 | ``` 195 | @prefix dc10: . 196 | @prefix dc11: . 197 | 198 | _:a dc10:title "SPARQL Query Language Tutorial" . 199 | _:a dc10:creator "Alice" . 200 | 201 | _:b dc11:title "SPARQL Protocol Tutorial" . 202 | _:b dc11:creator "Bob" . 203 | 204 | _:c dc10:title "SPARQL" . 205 | _:c dc11:title "SPARQL (updated)" . 206 | ``` 207 | 208 | 我们匹配拥有属性`dc10:title`或`dc11:title`的三元组,查询语句为: 209 | 210 | ``` 211 | PREFIX dc10: 212 | PREFIX dc11: 213 | 214 | SELECT ?title 215 | WHERE { 216 | { 217 | ?book dc10:title ?title . 218 | } UNION { 219 | ?book dc11:title ?title . 220 | } 221 | } 222 | ``` 223 | 224 | 查询结果为: 225 | 226 | ![sparql-example-16.png](../../images/sparql-example-16.png) 227 | 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /notes/tdb.md: -------------------------------------------------------------------------------- 1 | # TDB 2 | 3 | ## 1. 简介 4 | 5 | TDB是Jena框架的一个组成部分,用于存储和检索RDF数据的数据库,它可以用于在`单机`高效地存储RDF。 6 | 7 | TDB中提供`事务(transaction)`的机制,可以保证数据安全地进行操作,避免意外地中断造成的数据丢失等问题。 8 | 9 | 在Fuseki中,内置了TDB进行数据存储和SPARQL的查询。 10 | 11 | 12 | ### 1.1 入门基本操作 13 | 14 | 1. 构建TDB数据库 15 | 2. 连接TDB数据库 16 | 3. 进行事务操作 17 | 18 | ![完整示例](../tdb/TDBDatasetExample.java) 19 | 20 | ### 1.2 批量导入Bulkloader 21 | 22 | 我们可以使用`Bulkloader`来批量导入数据,在Jena中提供了命令行工具tdbloader来实现 23 | 24 | ```shell 25 | tdbloader.bat --loc database[tdb数据库目录] rdfFile[要导入的数据的文件名] 26 | ``` 27 | 28 | 运行1.1的示例之后,我们会在根目录下创建一个TDB数据库(dataset目录下),我们使用命令行工具目录下的`sparql-example.ttl`文件数据导入到dataset数据中。 29 | 30 | 31 | ![tdb-01](../images/tdbloader.png) 32 | 33 | 导入之后,再运行1.1示例中的TDBDatasetExample.connect(),打印出数据 34 | 35 | ![tdb-02](../images/tdbloader-results.png) 36 | 37 | 我们在数据集上运行查询语句,[完整示例](../tdb/TDBQueryExample.java) 38 | 39 | ## 2. TDB的设计 40 | 41 | ### 2.1 概述 42 | 43 | TDB将数据集存储在单个目录下的文件系统中,一个数据集包含 44 | 45 | 1. node table(节点表),并非传统SQL中的表 46 | 2. Triple/Quad indexes(三元组/四元组索引) 47 | 3. prefixes table(存储命名空间前缀的表) 48 | 49 | ### 2.2 The Node Table 50 | 51 | `Node Table`实际上是一个字典(dictionary),提供了`node(节点)`和`nodeid(节点id)`之间的双向映射。 52 | 53 | 在进行查询的过程中,经常会使用到`nodeid` -> `node`的映射,因此在Node Table的实现上,用来一个缓存来存储这样的结果。?? 54 | 55 | NodeId是一个8字节的数字,从Node到Nodeid的映射是基于Node的hash值(128字节的MD5哈希值) 56 | 57 | node table的存储是这样的结构 58 | 59 | 1. 一个顺序的文件映射`nodeId`到`node` 60 | 2. 一个B+ tree从映射node到nodeid 61 | 62 | ### 2.3 Triple and Quad Indexes 63 | 64 | 三元组用于`default graph`(默认的rdf图),四元组则是在三元组的基础上多一个一个图的IRI,用于`named graph`(命名的图),可以用于多图数据检索。 65 | 66 | 由于在SQL中,并没有`triple table`可以直接存储三元组数据,因此在TDB中,所谓的`triple table`其实是三张表的索引保存在一起。而TDB提供了三张表的管理,暴露在外面的接口可以直接操作三元组。 67 | 68 | ### 2.4 Prefixes Table 69 | 70 | `Prefixes Table`使用了一个`node table`和一个索引(Graph->Prefix->URI),通常非常地小,且不参与到查询的过程中。 71 | 72 | 一般来说,只在序列化三元组数据,将其保存为`RDF/XML`或`Turtle`格式的文件中会使用到这个表。 73 | 74 | ### 2.5 Inline Values 75 | 76 | 暂时看不懂 77 | 78 | ### 2.6 Query Processing 79 | 80 | TDB提供了一些底层次的图模式的优化, 81 | 82 | ## 3. TDB 数据集 83 | 84 | 一个RDF数据集可以是一个未命名的rdf图和零到多个命名的rdf图的集合。默认情况下,是在default graph进行SPARQL查询。 85 | 86 | ### 3.1 数据集存储 87 | 88 | TDB使用文件(目录)来存储数据集。 89 | 90 | 未命名的rdf graph会被存储为三元组,而命名的rdf graph则会被存储为四元组(即多了一个索引) 91 | 92 | 通过相同的文件路径(目录)和TDBFactory.createDataset(theSameLoaction)在JVM创建的每个数据集都是相同的。 93 | 94 | *在这里看来,TDB应该是一个内存数据库,把所有的数据载入到内存中,再进行计算操作。而所谓的缓存,是利用多余的bit为来加载一些数据。* 95 | 96 | ### 3.2 数据查询 97 | 98 | 在查询RDF数据时,命名的rdf graph和default的rdf graph会被区分开来,所有的命名的rdf graph可以被当作一个单独的图(所有的命名图可以进行联合操作)。 99 | 100 | ### 3.3 特殊的图名称 101 | 102 | 在TDB中提供 103 | 104 | |URI|说明| 105 | |:--|:--| 106 | |urn:x-arq:UnionGraph|查询在RDF数据中所有合并的命名的rdf图| 107 | |urn:x-arq:DefaultGraph|数据集默认的rdf图,使用这个URI时,意味着查询默认的图是一个`union graph`| 108 | 109 | ## 3. TDB Java API 110 | 111 | ### 2.1 连接数据集 112 | 113 | `TDBFactroy`类中包含了静态的工厂方法,可以用于连接数据集,在使用之后可以关闭连接之后,所有的更新操作会被保存到硬盘中。 114 | 115 | 数据集可以以两种方式提供 116 | 117 | 1. 目录路径 118 | 2. assembler文件 119 | 120 | #### 2.1.1 使用目录路径 121 | 122 | 使用这种方式,当提供的目录为空时,TDB 会建立文件的索引和node table(节点表格)。在存在数据的情况下,TDB会直接连接到已存在数据。 123 | 124 | ```java 125 | // 创建一个TDB支撑的数据集 126 | String directory = "MyDatabases/Dataset1"; 127 | Dataset dataset = TDBFactory.createDataset(directory); 128 | 129 | ``` 130 | 131 | 132 | #### 2.1.2 使用assembler文件 133 | 134 | ## 5. 事务 135 | 136 | ### 5.1 事务简介 137 | 138 | TDB使用`write-ahead-logging`的机制来支持`ACID事务`。 139 | 140 | 通过事务可以提高TDB数据库的健壮性。 141 | 142 | TDB事务可以同时支持一个写事务操作和多个读事务。 143 | 144 | ### 5.2 不足 145 | 146 | 1. Bulk loads : TDB的bulk loader不支持事务 147 | 2. 不支持嵌套的事务 148 | 3. Some active transaction state is held exclusively in-memory, limiting scalability. 149 | 4. Long-running transactions. Read-transactions cause a build-up of pending changes; 150 | 151 | ### 5.3 事务API 152 | 153 | #### 5.3.1 读事务 154 | 155 | 基本语法 156 | 157 | ```java 158 | dataset.begin(ReadWrite.READ); 159 | try { 160 | // 进行读操作 161 | } finally { 162 | dataset.end(); 163 | } 164 | ``` 165 | 166 | 使用`dataset.begin(ReadWrite.READ)`开始一个读事务,然后使用一个`dataset.end()`来表明一个事务的结束。 167 | 168 | 此外,也可以使用`data.commit()`或`dataset.abort()`来结束一个事务。 169 | 170 | #### 5.3.2 写事务 171 | 172 | 写事务可以用于SPARQL查询、SPARQL更新操作和任何修改数据的行为。 173 | 174 | 注意`model.read`操作会消耗大量临时的空间。 175 | 176 | 基本模式为 177 | 178 | ```java 179 | dataset.begin(ReadWrite.WRITE); 180 | try{ 181 | // 182 | dataset.commit(); 183 | } finally { 184 | dataset.end(); 185 | } 186 | ``` 187 | 188 | ## 6. 多线程使用 189 | 190 | 多线程共享rdf数据有两种模式 191 | 192 | 1. 一个数据集对象,在两个线程中使用。 193 | 2. 不同线程共享存储,分别创建自己的数据集对象,有独立的事务操作。 194 | 195 | ### 6.1 模式1示例 196 | 197 | 有一个全局的数据集对象 198 | 199 | ```java 200 | Dataset dataset = TDBFactory.createDataset(location); 201 | ``` 202 | 203 | 有两个线程thread1和thread2共享这个数据集对象, 204 | 205 | thread1 206 | 207 | ```java 208 | dataset.begin(ReadWrite.WRITE); 209 | try { 210 | // 211 | dataset.commit() 212 | } finally { 213 | dataset.end(); 214 | } 215 | ``` 216 | 217 | thread2 218 | 219 | ```java 220 | dataset.begin(ReadWrite.READ); 221 | try { 222 | // 223 | } finally {dataset.end();} 224 | ``` 225 | 226 | ### 6.2 模式2示例 227 | 228 | 在各自的线程上,对同一个数据创建各自的数据集对象`Dataset dataset`,拥有各自的事务。 229 | 230 | thread1 231 | 232 | ```java 233 | Dataset dataset = TDBFactory.createDataset(location); 234 | dataset.begin(ReadWrite.WRITE); 235 | try { 236 | // .. 237 | dataset.commit(); 238 | } finally {dataset.end();} 239 | ``` 240 | 241 | thread2 242 | 243 | ```java 244 | Dataset dataset = TDBFactory.createDataset(location); 245 | dataset.begin(ReadWrite.READ); 246 | try { 247 | // ... 248 | } finally { 249 | dataset.end(); 250 | } 251 | ``` 252 | 253 | ## 7. 多个JVM 254 | 255 | 在不同JVM运行的应用程序不能同时共享同一份数据文件(高危,有很大机率会损坏数据)。 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /notes/sparql/06否定过滤器.md: -------------------------------------------------------------------------------- 1 | # SPARQL 1.1 Query Language 2 | 3 | W3C Recommendation 21 March 2013 4 | 5 | [原文地址](https://www.w3.org/TR/sparql11-query/) 6 | 7 | ## 6. 否定过滤器(Negation) 8 | 9 | ### 6.1 使用图模式进行过滤 10 | 11 | 在SPARQL中,我们可以通过关键字`FILTER EXISTS`+{}或`FILTER NOT EXISTS`+{}的方式来对结果集进行过滤。 12 | 13 | *{}表示图模式* 14 | 15 | 举个例子 16 | 17 | ``` 18 | @prefix : . 19 | @prefix rdf: . 20 | @prefix foaf: . 21 | 22 | :alice rdf:type foaf:Person . 23 | :alice foaf:name "Alice" . 24 | :bob rdf:type foaf:Person . 25 | ``` 26 | 27 | 使用图模式去除存在`foaf:name`属性的三元组。 28 | 29 | ``` 30 | PREFIX foaf: 31 | PREFIX rdf: 32 | 33 | SELECT ?person 34 | WHERE { 35 | ?person rdf:type foaf:Person . 36 | FILTER NOT EXISTS { 37 | ?person foaf:name ?name . 38 | } 39 | } 40 | ``` 41 | 42 | ![sparql-example-17.png](../../images/sparql-example-17.png) 43 | 44 | 使用图模式筛选出存在`foaf:name`属性的三元组, 45 | 46 | ``` 47 | PREFIX foaf: 48 | PREFIX rdf: 49 | 50 | SELECT ?person 51 | WHERE { 52 | ?person rdf:type foaf:Person . 53 | FILTER EXISTS { 54 | ?person foaf:name ?name . 55 | } 56 | } 57 | ``` 58 | 59 | 其实这样写就等价于 60 | 61 | ``` 62 | PREFIX foaf: 63 | PREFIX rdf: 64 | 65 | SELECT ?person 66 | WHERE { 67 | ?person rdf:type foaf:Person . 68 | ?person foaf:name ?name . 69 | } 70 | ``` 71 | 72 | ![sparql-example-18.png](../../images/sparql-example-18.png) 73 | 74 | ### 6.2 去除可能的结果集 75 | 76 | 在SPARQL中,可以通过关键字`MINUS`来进行条件过滤。还是以上面的例子作为数据,我们可以编写出跟使用`FILTER NOT EXISTS`一样结果的查询语句: 77 | 78 | ``` 79 | PREFIX foaf: 80 | PREFIX rdf: 81 | 82 | SELECT ?person 83 | WHERE { 84 | ?person rdf:type foaf:Person . 85 | MINUS { 86 | ?person foaf:name ?name . 87 | } 88 | } 89 | ``` 90 | 91 | 查询结果还是一样的 92 | 93 | ![sparql-example-19.png](../../images/sparql-example-19.png) 94 | 95 | ### 6.3 NOT EXISTS vs MINUS 96 | 97 | 在SPARQL提供了这两种否定过滤器(可以这样理解),从上面例子来看,两者其实很类似。这一节也是来说明两种细微的差别,从而加深对两种方式的理解。 98 | 99 | 它们的区别在于:MINUS语句块中的变量是与匹配模式的作用域是相同的,也就是说`变量共享`,而NOT EXISTS的作用域则是分隔开来的。 100 | 101 | 还是通过几个例子来说明吧: 102 | 103 | ``` 104 | @prefix : . 105 | :a :b :c . 106 | ``` 107 | 108 | NOT EXISTS的方式来查询 109 | 110 | ``` 111 | SELECT * 112 | WHERE { 113 | ?s ?p ?o . 114 | FILTER NOT EXISTS { 115 | ?x ?y ?z 116 | } 117 | } 118 | ``` 119 | 120 | ![sparql-example-20.png](../../images/sparql-example-20.png) 121 | 122 | 这个查询大致的过程是`?s ?p ?o`模式对数据进行匹配,然后再进行`?x ?y ?z`的模式匹配,去除交集,剩下的数据就为空。 123 | 124 | 而MINUS则不同, 125 | 126 | ``` 127 | SELECT * 128 | WHERE { 129 | ?s ?p ?o . 130 | MINUS { 131 | ?x ?y ?z 132 | } 133 | } 134 | ``` 135 | 136 | 查询的大致过程是`?s ?p ?o`模式对数据进行匹配,之后在此数据集中,进行二次匹配,由于变量相关,即`?s ?p ?o`都指定了匹配的变量,而本例子中使用`?x ?y ?z`跟上面的三元组模式没有共同的变量,应该匹配为空,或者说无法进行预期的匹配。 137 | 138 | 为了验证我们的想法,我们对MINUS的查询稍作修改。 139 | 140 | ``` 141 | SELECT * 142 | WHERE { 143 | ?s ?p ?o . 144 | MINUS { 145 | ?s ?p ?x . 146 | } 147 | } 148 | ``` 149 | 150 | 这个时候,由于`?s ?p ?x`可以匹配到`?s ?p ?o`匹配到所有结果,那么结果集就应该为空,执行结果如下: 151 | 152 | ![sparql-example-21.png](../../images/sparql-example-21.png) 153 | 154 | 我们再拿上一个数据示例来分析。我们将MINUS中的查询语句做一点小修改就可以看到结果的不同。 155 | 156 | ``` 157 | PREFIX foaf: 158 | PREFIX rdf: 159 | 160 | SELECT ?person 161 | WHERE { 162 | ?person rdf:type foaf:Person . 163 | MINUS { 164 | ?p foaf:name ?name . 165 | } 166 | } 167 | ``` 168 | 169 | 注意到,我们把MINUS语句块中的`?person`改成了`?p`这个时候,就由于两个匹配模式没有`共同的变量`,导致查询结果为: 170 | 171 | ![sparql-example-22.png](../../images/sparql-example-22.png) 172 | 173 | 关于这一部分的理解,我们可以通过 174 | 175 | ### 6.4 内部的FILTER 176 | 177 | 我们再来讨论一个更加复杂的情况,那就是在NOT EXISTS和MINUS语句块加入`FILTER`的情况,来加深对变量的作用域,共享问题的理解。 178 | 179 | 举个例子,来看看两者的区别。 180 | 181 | ``` 182 | @prefix : . 183 | :a :p 1 . 184 | :a :q 1 . 185 | :a :q 2 . 186 | 187 | :b :p 3.0 . 188 | :b :q 4.0 . 189 | :b :q 5.0 . 190 | ``` 191 | 192 | *官方文档这部分经本人实验,是错误的* 193 | 194 | 使用FILTER NOT EXISTS,会把作用域进行切割,我们可以通过`--debug`清晰地看到查询语句执行的结果: 195 | 196 | ``` 197 | PREFIX : 198 | SELECT * 199 | WHERE { 200 | ?x :p ?n . 201 | FILTER NOT EXISTS { 202 | ?x :q ?m . 203 | FILTER(?n = ?m) 204 | } 205 | } 206 | ``` 207 | 208 | ![sparql-example-23.png](../../images/sparql-example-23.png) 209 | 210 | 可以看到以下的结构 211 | 212 | ``` 213 | ( 214 | sequence 215 | ( 216 | filter ( 217 | notexists 218 | (table empty) 219 | ) 220 | (table unit) 221 | ) 222 | ( 223 | bgp (triple ?x ?n) 224 | ) 225 | ) 226 | ``` 227 | 228 | 也就是说查询时,在FILTER NOT EXISTS中的?n其实是不存在的,导致查询结果为空,因此最终结果为`:a`和`:b` 229 | 230 | 要想达到官网的结果,应该将查询语句改为: 231 | 232 | ``` 233 | // 如果要达到所预期的查询效果应该是这样 234 | PREFIX : 235 | SELECT ?x ?n 236 | WHERE { 237 | ?x :p ?n . 238 | FILTER NOT EXISTS { 239 | ?y :q ?m . 240 | ?y :q ?n . 241 | FILTER(?n = ?m) 242 | } 243 | } 244 | ``` 245 | 246 | ![sparql-example-24.png](../../images/sparql-example-24.png) 247 | 248 | 那么在MINUS中,是什么情况?我们来看看官网上的例子执行的具体过程。 249 | 250 | ``` 251 | PREFIX : 252 | SELECT * 253 | WHERE { 254 | ?x :p ?n 255 | MINUS { 256 | ?x :q ?m . 257 | FILTER(?n = ?m) 258 | } 259 | } 260 | ``` 261 | 262 | ![sparql-example-25.png](../../images/sparql-example-25.png) 263 | 264 | 总结一下: 265 | 266 | **无论是MINUS还是FILTER NOT EXISTS中,FILTER都不能获取语句块外部的变量,由于本人使用的JENA中的一个SPARQL命令行工具,所以暂时不清楚是一个bug,还是标准文档中描述有错误。** 267 | 268 | -------------------------------------------------------------------------------- /notes/sparql/sparql.md: -------------------------------------------------------------------------------- 1 | # SPARQL 2 | 3 | [中文学习文档](http://www.chinaw3c.org/REC-sparql11-overview-20130321-cn.html) 4 | [搭建测试环境](http://jena.apache.org/tutorials/sparql_query1.html) 5 | 6 | ## 1. 概述 7 | 8 | SPARQL 1.1 是一组W3C推荐标准,提供了对Web上或RDF存储(RDF store)中的RDF图内容(graph)进行查询和处理的语言和协议。它包含以下几个部分: 9 | 10 | 1. 查询语言:一个面向RDF的查询语言 11 | 2. 查询结果格式处理:SPARQL查询结果提供了多种格式,例如json,csv,xml等等。 12 | 3. 联邦查询:此规范定义了一个SPARQL 1.1查询语言扩展,用来在分布的多个SPARQL端点(endpints)上执行SPARQL查询。 13 | 4. Entailment Regimes(蕴含):此规范定义了RDF Schema,OWL或RIF等蕴含规则下的SPARQL查询语义。 14 | 5. update(更新):一个面向RDF graph的更新语言。 15 | 6. RDF协议:该协议定义了一种方法,执行任意的SPARQL查询,并将结果更新到一个SPARQL服务。 16 | 7. 服务描述:该规范定义了一个标准方法,用来发现SPARQL服务,并提供了描述SPARQL服务所需要的词汇表。 17 | 8. 图存储HTTP协议:相对于完整的SPARQL协议,该文档定义了一个最小子集,基于常用的HTTP协议的操作,管理RDF graph的内容。 18 | 9. 测试用例:这是一组测试,帮助理解规范,并检测一个系统是否符合SPARQL 1.1规范。 19 | 20 | ## 2. 搭建sparql测试环境 21 | 22 | 1. 下载解压包,[下载地址](http://jena.apache.org/) 23 | 2. 解压,添加环境变量:JENA_HOME : D:\apache-jena-3.1.0 24 | 3. 可以把sparql命令添加到系统变量PATH : %JENA_HOME%\bat 25 | 4. 运行sparql --version检测是否安装成功 26 | 27 | 安装过程中的问题 28 | 29 | 出现了Unsupported major.minor version 51.0 30 | 因为使用了过低版本的jdk1.6而出现的问题,换成jdk1.8后问题解决; 31 | 32 | 有了这个之后,就可以进行sparql查询的练习,例如,我们使用[Turtle](https://www.w3.org/TeamSubmission/turtle/)来表示Alice的信息,有 33 | 34 | ``` 35 | @prefix foaf: . 36 | @prefix rdfs: . 37 | a foaf:Person . 38 | foaf:name "Alice" . 39 | foaf:mbox . 40 | foaf:knows . 41 | foaf:knows . 42 | foaf:name "Bob" . 43 | foaf:knows . 44 | foaf:knows . 45 | foaf:name "Charlie" . 46 | foaf:knows . 47 | foaf:name "Snoopy"@en . 48 | ``` 49 | 50 | 然后使用sparql查询语句,对其进行查询,查询的执行命令为 51 | 52 | ```sql 53 | sparql --data=sparql-exampe.ttl --query=example.rq --results=JSON 54 | ``` 55 | 56 | 其中 57 | 58 | * data : 数据集(rdf/ttl等) 59 | * query : 查询脚本 60 | * results : 指定返回格式,有text,XML,JSON,CSV,TSV,Graph,默认是表格形式 61 | 62 | 那么接下来,就了解一下如何使用sparql来操作这个数据, 63 | 64 | ## 3. SPARQL 1.1 查询语言 65 | 66 | 一段简单的sparql查询如下: 67 | 68 | ``` 69 | PREFIX foaf: 70 | SELECT ?name (COUNT(?friend) AS ?count) 71 | WHERE { 72 | ?person foaf:name ?name . 73 | ?person foaf:knows ?friend . 74 | } GROUP BY ?person ?name 75 | ``` 76 | 77 | sparql 1.0查询包括了 78 | 79 | * 联表查询(union) 80 | * 可选查询部分(optional query parts) 81 | * 过滤器(filters) 82 | 83 | sparql 1.1查询有新增了 84 | 85 | * 子查询(subqueries) 86 | * 赋值(value assignment) 87 | * 路径表达(path expression) 88 | * 聚合查询(aggregates) 89 | 90 | 除了`SELECT`查询之外,还支持的查询有 91 | 92 | * ASK查询,返回值为yes/no值 93 | * CONSTRUCT查询,根据查询结果构造RDF图 94 | 95 | ### 4. SPARQL 的不同查询结果格式 96 | 97 | 在SPARQL语言中,SELECT查询的返回结果包含一组从变量到RDF项(RDF terms)的映射,通常以表格的方式表达。 98 | 99 | ![sparql-results-table.png](../../images/sparql-results-table.png) 100 | 101 | 为了以机器可读的方式交换这些查询结果,SPARQL支持四种常见的交换格式: 102 | 103 | * XML 104 | * JSON 105 | * CSV 106 | * TSV 107 | 108 | ![sparql-results-json.png](../../images/sparql-results-json.png) 109 | 110 | 111 | ### 5. SPARQL 1.1 联邦查询(Federated Query) 112 | 113 | 联邦查询指的是能够显示地将指定的查询代理给另一个SPARQL端点。 114 | 115 | 举例来说,在上面的例子,如果要知道Alice的朋友中有谁和DBpedia的资源描述符IRI\具有相同的名字。为了完成这一查询,需要将获得朋友名字的查询发送给一个地址为`http://dbpedia.org/sparql`的SPARQL端点,通过`SERVICE`关键字找出具有名字\,具体查询为 116 | 117 | ``` 118 | PREFIX foaf: 119 | SELECT ?name 120 | WHERE { 121 | foaf:knows [ foaf:name ?name ] . 122 | SERVICE { foaf:name ?name } 123 | } 124 | ``` 125 | 126 | 其中,查询的模式的第一部分位于查询的 WHERE 部分,这部分仍然匹配的是本地的SPARQL服务,而后续对模式的处理,则通过SERVICE关键字代理给指定的远程SPARQL服务。 127 | 128 | ### 6. 蕴含机制(Entailment Regimes) 129 | 130 | SPARQL可以与RDF Schema或OWL Axioms等本体信息一起使用。SPARQL 1.1蕴含规范定义了在不同的蕴含规则下,如何对这种查询做出响应,定义的蕴含规则包括 RDF、RDF Schema、D-Entailment (RDF-MT)、OWL (OWL2-Overview),及RIF (RIF-Overview)。 131 | 132 | 举例来说,假定在Alice的数据之外,还有基于RDF Schema和OWL描述的本体信息FOAF词汇表,里面有内容为 133 | 134 | ``` 135 | @prefix foaf: . 136 | @prefix rdfs: . 137 | foaf:name rdfs:subPropertyOf rdfs:label . 138 | ``` 139 | 140 | 可以看到`foaf:name`是`foaf:label`的一个子属性,那么由于蕴含机制,查询所有人的标签(labels),如下 141 | 142 | ``` 143 | SELECT ?label 144 | WHERE { 145 | ?person rdfs:label ?label 146 | } 147 | ``` 148 | 149 | 就会返回 150 | 151 | ![sparql-entailment.png](../../images/sparql-entailment.png) 152 | 153 | ### 7. 更新语言 154 | 155 | SPARQL 1.1更新(update)定义了SPARQL 1.1 更新请求的语法和语义,并提供了不同用途的例子,更新操作可以由一组顺序执行的序列组成,对图存储(Graph Store)中的一组图进行更新,对图存储中进行RDF图的更新,创建和删除操作。 156 | 157 | 注意:使用更新操作,就必须使用`update.bat`或`update`脚本来执行rq文件,语法如下 158 | 159 | ``` 160 | update --data=data.ttl --update=update.rq --dump 161 | ``` 162 | 163 | 更新的操作不会保存到文件里面,而是在内存中改变,`--dump`可以将其内存中改变后的模型打印到控制台,然后也可以通过管道保存到文件中。 164 | 165 | 一个insert的例子 166 | 167 | ``` 168 | PREFIX foaf: 169 | INSERT DATA { foaf:knows [ foaf:name "Dorothy" ]. } ; 170 | ``` 171 | 172 | ![sparql-insert.png](../../images/sparql-insert.png) 173 | 174 | ### 8. SPARQL 1.1 协议 175 | 176 | 面向RDF查询的SPARQL 1.1协议定义了如何通过HTTP协议,将一个SPARQL 1.1查询及请求发送给一个SPARQL服务。该文档也定义了如何将这些请求映射为HTTP GET和POST操作,以及这些请求的HTTP响应。 177 | 178 | ### 9. SPARQL 1.1 服务描述 179 | 180 | SPARQL 1.1服务描述文档给出了一种发现基于SPARQL 1.1协议的SPARQL服务的方法,以及一个描述SPARQL服务的词汇表。 181 | 182 | 在这份文档中,当一个SPARQL的服务端点(Service Endpoint)收到不包含任何查询或更新请求的HTTP GET请求时,应当返回一个关于该服务的 RDF描述。例如,当如下的HTTP请求 183 | 184 | ``` 185 | GET /sparql/ HTTP/1.1 186 | Host: www.example.org 187 | ``` 188 | 189 | 发送给地址为http://www.example.org/sparql/的SPARQL服务时,应当返回一个基于服务发现词汇表(Service Description Vocabulary)的RDF描述。这些描述可以提供关于该服务端点的默认数据集、所支持的SPARQL查询的功能特性、支持的蕴含种类等信息。 190 | 191 | ### 10. SPARQL 1.1 图存储的HTTP协议 192 | 193 | 对许多处理RDF数据的应用程序和服务来说,并不需要完整的SPARQL 1.1更新语言,因此SPARQL1.1图存储HTTP协议提供了一种基于HTTP的操作实现管理一组图数据的部分操作的方法。 194 | 195 | 例如,在前面的向RDF插入一个三元组,在支持SPARQL 1.1图存储HTTP协议的SPARQL服务上,这个插入操作可以直接通过执行一个 HTTP POST 将其载荷(payload)作为RDF元组直接插入RDF图,而无需发送一个完整的SPARQL 1.1更新请求。 196 | 197 | ``` 198 | POST /rdf-graphs/service?graph=http%3A%2F%2Fwww.example.org%2Falice HTTP/1.1 199 | Host: example.org 200 | Content-Type: text/turtle 201 | @prefix foaf: . 202 | foaf:knows [ foaf:name "Dorothy" ] . 203 | ``` 204 | 205 | 在SPARQL 1.1图存储HTTP协议中,还定义了其他用于修改目的的直接HTTP修改RDF图(如用HTTP PUT替换整个图,用HTTP DELETE删除一个RDF图等)或获取RDF图(如通过HTTP GET)等。可以将这一组协议看作结合SPARQL 1.1查询 和SPARQL 1.1更新的完整SPARQL 1.1协议的一个轻量级替代版。 --------------------------------------------------------------------------------