对于输入的一个数据元素(单元格)中的多个复杂实体,在不清理输入数据的情况下,RML 是否有解决方案?
Is there a solution in RML for multiple complex entities in one data element (cell) of the input without cleaning the input data?
我有一个人名列表,例如,除了(Person
是列名):
Person
"Wilson, Charles; Harris Arthur"
"White, D.
Arthur Harris"
请注意,提到多个人的方式不同,分隔也不同。
我想使用 RDF 映射语言 https://rml.io/ 创建以下 RDF 而无需清理(或更改)输入数据:
:Wilson a foaf:Person;
foaf:firstName "Charles";
foaf:lastName "Wilson" .
:Harris a foaf:Person;
foaf:firstName "Arthur";
foaf:lastName "Harris" .
:White a foaf:Person;
foaf:firstName "D.";
foaf:lastName "White" .
请注意,Arthur Harris 在输入数据中被提及两次,但只创建了一个 RDF 资源。
我使用函数 ontology https://fno.io/ 并创建了自定义 java 方法。基于参数 mode
返回人员属性列表(例如,仅 URI 或仅名字)。
public static List<String> getPersons(String value, String mode) {
if(mode == null || value.trim().isEmpty())
return Arrays.asList();
List<String> results = new ArrayList<>();
for(Person p : getAllPersons(value)) {
if(mode.trim().isEmpty() || mode.equals("URI")) {
results.add("http://example.org/person/" + p.getLastName());
} else if(mode.equals("firstName")) {
results.add(p.getFirstName());
} else if(mode.equals("lastName")) {
results.add(p.getLastName());
} else if(mode.equals("fullName")) {
results.add(p.getFullName());
}
}
return results;
}
假设 getAllPersons
方法正确地从给定的字符串中提取人物,就像上面的那样。
为了从一个单元格中提取多个人,我在 subjectMap
中调用 getPersons
函数,如下所示:
:tripleMap a rr:TriplesMap .
:tripleMap rml:logicalSource :ExampleSource .
:tripleMap rr:subjectMap [
fnml:functionValue [
rr:predicateObjectMap [
rr:predicate fno:executes ;
rr:objectMap [ rr:constant cf:getPersons ]
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter ;
rr:objectMap [ rml:reference "Person" ] # the column name
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter2 ;
rr:objectMap [ rr:constant "URI" ] # the mode
]
];
rr:termType rr:IRI ;
rr:class foaf:Person
] .
我使用 RLMMapper https://github.com/RMLio/rmlmapper-java, however, it only allows to return one subject for each line, see https://github.com/RMLio/rmlmapper-java/blob/master/src/main/java/be/ugent/rml/Executor.java#L292。
这就是为什么我写了一个 List<ProvenancedTerm> getSubjects(Term triplesMap, Mapping mapping, Record record, int i)
方法并相应地替换它的原因。
这导致以下结果:
:Wilson a foaf:Person .
:Harris a foaf:Person .
:White a foaf:Person .
我知道此扩展与 RML 规范不兼容 https://rml.io/specs/rml/,其中规定如下:
It [a triples map] must have exactly one subject map that specifies how to generate a subject for each row/record/element/object of the logical source (database/CSV/XML/JSON data source accordingly).
如果我继续添加名字 resp。姓,可以添加以下 predicateObjectMap
:
:tripleMap rr:predicateObjectMap [
rr:predicate foaf:firstName;
rr:objectMap [
fnml:functionValue [
rr:predicateObjectMap [
rr:predicate fno:executes ;
rr:objectMap [ rr:constant cf:getPersons ]
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter ;
rr:objectMap [ rml:reference "Person" ] # the column name
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter2 ;
rr:objectMap [ rr:constant "firstName" ] # the mode
]
]
]
] .
因为 predicateObjectMap
对每个主题进行评估,现在返回多个主题,每个人资源将获得每个人的名字。为了更清楚,看起来像这样:
:Wilson a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
:Harris a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
:White a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
我的问题是:在不清理(或更改)输入的情况下,RML 中是否存在针对输入的一个数据元素(单元格)中的多个复杂实体(例如,具有名字和姓氏的人)的解决方案或变通方法数据?
也许这个问题与我的问题有关:https://www.w3.org/community/kg-construct/track/issues/3
如果这样的用例不打算通过像 RML 这样的映射框架来解决,那也很好。如果是这种情况,还有什么替代方案?例如,生成 RDF 的手工提取管道?
据我所知,使用 FnO 函数和连接条件无法实现您的尝试。
但是,您可以尝试指定一个巧妙的 rml:query
或 rml:iterator
,在复数值到达 RLMMapper 之前将其拆分。不过,这是否可能取决于特定的源数据库。
例如,如果源是 SQL 服务器数据库,您可以使用函数 STRING_SPLIT. Or if it is a PostgreSQL database, you could use STRING_TO_ARRAY together with unnest。 (由于数据中使用了不同的分隔符,您可能必须为每个不同的分隔符调用一次 STRING_SPLIT 或 STRING_TO_ARRAY。
如果您提供有关底层数据库的更多信息,我可以用示例更新此答案
(注意:我为 RML 及其技术做出贡献。)
据我了解,您遇到了归一化问题(多值单元格)。当然,您要求的是在 1NF 中拥有一个数据集,请参阅:https://en.wikipedia.org/wiki/First_normal_form
要解决 CSV 文件中这些常见的异质性问题,您可以在 Web 注释(W3C 推荐)上使用 CSV。更详细地说,您在这种情况下要求的 属性 是 csvw:separator
(https://www.w3.org/TR/tabular-data-primer/#sequence-values).
但是CSVW的解析器并不多,其属性生成RDF的语义也不是很清楚。我们一直在研究一种与 CSVW 和 RML+FnO 一起工作的解决方案,以从表格数据生成虚拟 KG(还有一个 SPARQL 查询作为输入,而不是将输入数据集转换为 RDF)。我们提议的输出是一个结构良好的数据库,带有标准 [R2]RML 映射,因此任何符合 [R2]RML 的都可以用来回答查询或实现知识图谱。虽然我们目前不支持具体化步骤,但它在我们的 ToDo 列表中。
你可以看一下投稿(正在审核中):http://www.semantic-web-journal.net/content/enhancing-virtual-ontology-based-access-over-tabular-data-morph-csv
我有一个人名列表,例如,除了(Person
是列名):
Person
"Wilson, Charles; Harris Arthur"
"White, D.
Arthur Harris"
请注意,提到多个人的方式不同,分隔也不同。
我想使用 RDF 映射语言 https://rml.io/ 创建以下 RDF 而无需清理(或更改)输入数据:
:Wilson a foaf:Person;
foaf:firstName "Charles";
foaf:lastName "Wilson" .
:Harris a foaf:Person;
foaf:firstName "Arthur";
foaf:lastName "Harris" .
:White a foaf:Person;
foaf:firstName "D.";
foaf:lastName "White" .
请注意,Arthur Harris 在输入数据中被提及两次,但只创建了一个 RDF 资源。
我使用函数 ontology https://fno.io/ 并创建了自定义 java 方法。基于参数 mode
返回人员属性列表(例如,仅 URI 或仅名字)。
public static List<String> getPersons(String value, String mode) {
if(mode == null || value.trim().isEmpty())
return Arrays.asList();
List<String> results = new ArrayList<>();
for(Person p : getAllPersons(value)) {
if(mode.trim().isEmpty() || mode.equals("URI")) {
results.add("http://example.org/person/" + p.getLastName());
} else if(mode.equals("firstName")) {
results.add(p.getFirstName());
} else if(mode.equals("lastName")) {
results.add(p.getLastName());
} else if(mode.equals("fullName")) {
results.add(p.getFullName());
}
}
return results;
}
假设 getAllPersons
方法正确地从给定的字符串中提取人物,就像上面的那样。
为了从一个单元格中提取多个人,我在 subjectMap
中调用 getPersons
函数,如下所示:
:tripleMap a rr:TriplesMap .
:tripleMap rml:logicalSource :ExampleSource .
:tripleMap rr:subjectMap [
fnml:functionValue [
rr:predicateObjectMap [
rr:predicate fno:executes ;
rr:objectMap [ rr:constant cf:getPersons ]
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter ;
rr:objectMap [ rml:reference "Person" ] # the column name
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter2 ;
rr:objectMap [ rr:constant "URI" ] # the mode
]
];
rr:termType rr:IRI ;
rr:class foaf:Person
] .
我使用 RLMMapper https://github.com/RMLio/rmlmapper-java, however, it only allows to return one subject for each line, see https://github.com/RMLio/rmlmapper-java/blob/master/src/main/java/be/ugent/rml/Executor.java#L292。
这就是为什么我写了一个 List<ProvenancedTerm> getSubjects(Term triplesMap, Mapping mapping, Record record, int i)
方法并相应地替换它的原因。
这导致以下结果:
:Wilson a foaf:Person .
:Harris a foaf:Person .
:White a foaf:Person .
我知道此扩展与 RML 规范不兼容 https://rml.io/specs/rml/,其中规定如下:
It [a triples map] must have exactly one subject map that specifies how to generate a subject for each row/record/element/object of the logical source (database/CSV/XML/JSON data source accordingly).
如果我继续添加名字 resp。姓,可以添加以下 predicateObjectMap
:
:tripleMap rr:predicateObjectMap [
rr:predicate foaf:firstName;
rr:objectMap [
fnml:functionValue [
rr:predicateObjectMap [
rr:predicate fno:executes ;
rr:objectMap [ rr:constant cf:getPersons ]
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter ;
rr:objectMap [ rml:reference "Person" ] # the column name
] ;
rr:predicateObjectMap [
rr:predicate grel:valueParameter2 ;
rr:objectMap [ rr:constant "firstName" ] # the mode
]
]
]
] .
因为 predicateObjectMap
对每个主题进行评估,现在返回多个主题,每个人资源将获得每个人的名字。为了更清楚,看起来像这样:
:Wilson a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
:Harris a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
:White a foaf:Person;
foaf:firstName "Charles" ;
foaf:firstName "Arthur" ;
foaf:firstName "D." .
我的问题是:在不清理(或更改)输入的情况下,RML 中是否存在针对输入的一个数据元素(单元格)中的多个复杂实体(例如,具有名字和姓氏的人)的解决方案或变通方法数据?
也许这个问题与我的问题有关:https://www.w3.org/community/kg-construct/track/issues/3
如果这样的用例不打算通过像 RML 这样的映射框架来解决,那也很好。如果是这种情况,还有什么替代方案?例如,生成 RDF 的手工提取管道?
据我所知,使用 FnO 函数和连接条件无法实现您的尝试。
但是,您可以尝试指定一个巧妙的 rml:query
或 rml:iterator
,在复数值到达 RLMMapper 之前将其拆分。不过,这是否可能取决于特定的源数据库。
例如,如果源是 SQL 服务器数据库,您可以使用函数 STRING_SPLIT. Or if it is a PostgreSQL database, you could use STRING_TO_ARRAY together with unnest。 (由于数据中使用了不同的分隔符,您可能必须为每个不同的分隔符调用一次 STRING_SPLIT 或 STRING_TO_ARRAY。
如果您提供有关底层数据库的更多信息,我可以用示例更新此答案
(注意:我为 RML 及其技术做出贡献。)
据我了解,您遇到了归一化问题(多值单元格)。当然,您要求的是在 1NF 中拥有一个数据集,请参阅:https://en.wikipedia.org/wiki/First_normal_form
要解决 CSV 文件中这些常见的异质性问题,您可以在 Web 注释(W3C 推荐)上使用 CSV。更详细地说,您在这种情况下要求的 属性 是 csvw:separator
(https://www.w3.org/TR/tabular-data-primer/#sequence-values).
但是CSVW的解析器并不多,其属性生成RDF的语义也不是很清楚。我们一直在研究一种与 CSVW 和 RML+FnO 一起工作的解决方案,以从表格数据生成虚拟 KG(还有一个 SPARQL 查询作为输入,而不是将输入数据集转换为 RDF)。我们提议的输出是一个结构良好的数据库,带有标准 [R2]RML 映射,因此任何符合 [R2]RML 的都可以用来回答查询或实现知识图谱。虽然我们目前不支持具体化步骤,但它在我们的 ToDo 列表中。
你可以看一下投稿(正在审核中):http://www.semantic-web-journal.net/content/enhancing-virtual-ontology-based-access-over-tabular-data-morph-csv