作为SPARQL构造中的主题字面值查询
我很努力地创建一个正确的SPARQL查询,它将生成正确的格式,以便我可以在其中打开Protege。我们的本体论是关于鸡尾酒的,我们希望在我们的数据库中包含所有DBPedia鸡尾酒,包括配料(dbp:ingredients
)和配方(dbp:prep
)。在数据库中获得鸡尾酒的效果很好,但其成分和配方不是。现在我有以下查询:??作为SPARQL构造中的主题字面值查询
CONSTRUCT {?drink dct:subject ?category.
?drink dbp:prep ?recipe.
?drink dbp:ingredients ?ingredients.
?drink rdf:type owl:NamedIndividual .
?category rdf:type owl:Class.
dct:subject rdf:type owl:ObjectProperty.
dbp:prep rdf:type owl:ObjectProperty.
dbp:ingredient rdf:type owl:Objectproperty.
}
WHERE {
?drink dct:subject ?category.
?drink dbp:prep ?recipe.
?drink dbp:ingredients ?ingredients.}
由于原料和配方,现在没有宣布,它不会在门徒的个人标签显示。但是,当我加入这个到查询的构造物部分:
?recipe rdf:type owl:NamedIndividual.
?ingredients rdf:type owl:NamedIndividual.
我得到一个错误:
Virtuoso RDF01 Error Bad variable value in CONSTRUCT: "*5 cL vodka *10 cL orange juice" (tag 246 box flags 0) is not a valid subject, only object of a triple can be a literal
我想是因为准备和DBpedia的成分只是一个字符串,没有任何链接的数据。 但是,如何使这项工作在Protege中显示?
无法将字面值作为RDF三元组的主题。相反,创建配方和配料资源+将字符串值附加为rdfs:comment
(或者可能是rdfs:label
)可能是一种解决方法。它的工作原理是这样的:
CONSTRUCT {
?drink dct:subject ?category.
?drink dbp:prep ?recipe.
?drink dbp:ingredients ?ingredients.
?drink rdf:type owl:NamedIndividual .
?category rdf:type owl:Class.
dct:subject rdf:type owl:ObjectProperty.
dbp:prep rdf:type owl:ObjectProperty.
dbp:ingredients rdf:type owl:Objectproperty.
# add string values as rdfs:comment
?recipe rdfs:comment ?recipe_str .
?ingredients rdfs:comment ?ingredients_str
}
WHERE {
?drink dct:subject ?category.
?drink dbp:prep ?recipe_str.
?drink dbp:ingredients ?ingredients_str.
BIND(URI(CONCAT("http://dbpedia.org/resource/recipe", MD5(STR(?recipe_str)))) as ?recipe)
BIND(URI(CONCAT("http://dbpedia.org/resource/ingredients", MD5(STR(?ingredients_str)))) as ?ingredients)
}
注意,它会以某种方式如果配方(RESP成分)已经是一个资源失败。它不适用于DBpedia上的dbp:prep
和dbp:ingredients
,但一般来说,如果您不确定,并且您有一些实际上允许资源和文字的rdf:Property
,则需要正确处理此问题。通过使用IF-ELSE
结构:
BIND(IF(isLiteral(?recipe_str), URI(CONCAT("http://dbpedia.org/resource/recipe", MD5(STR(?recipe_str)))), ?recipe_str) as ?recipe)
BIND(IF(isLiteral(?ingredients_str), URI(CONCAT("http://dbpedia.org/resource/ingredients", MD5(STR(?ingredients_str)))), ?ingredients_str) as ?ingredients)
,你也必须省略rdfs:comment
三倍那么确实...
由于AKSW已经提供了一个很好的答案,我只是补充说'MD5()到另一种常见方法:' BIND(URI(concat(“http://example.com/coctailingrediants/”,ENCODE_FOR_URI(str(?ingredients_str))))AS?成分) BIND(URI(concat(“http://example.com/coctailrecipe/”,ENCODE_FOR_URI(str(?recipe_str))))AS?recipe) }'这是有风险的。 –
啊,谢谢你让我知道还有其他有用的方法,比如'ENCODE_FOR_URI' - 我从来没有使用过这种方法,但是对于长字符串,这可能就是你冒险的意思吗? – AKSW
非常感谢!它现在都在工作:) –
总之,文字不能科目。您应该声明数据属性 - 而不是对象属性 - 并使相应的文字成为它们的值。为了提取对象,似乎很难解析这些文字。也许你可以查询维基数据获取更多关于鸡尾酒的结构化信息(如果你想保留文本描述,可以使用DBpedia的联合查询)。顺便说一句:https://stackoverflow.com/a/44227937/7879193 –
因此,不可能将Literal声明为owl:NamedIndividual?或者,也许有任何方法来转换查询中的文字,以便这是可能的? –
IRI被用作'owl:NamedIndividual'的唯一标识符。 – AKSW