2017-10-16 111 views
0

我很努力地创建一个正确的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中显示?

+1

总之,文字不能科目。您应该声明数据属性 - 而不是对象属性 - 并使相应的文字成为它们的值。为了提取对象,似乎很难解析这些文字。也许你可以查询维基数据获取更多关于鸡尾酒的结构化信息(如果你想保留文本描述,可以使用DBpedia的联合查询)。顺便说一句:https://stackoverflow.com/a/44227937/7879193 –

+0

因此,不可能将Literal声明为owl:NamedIndividual?或者,也许有任何方法来转换查询中的文字,以便这是可能的? –

+0

IRI被用作'owl:NamedIndividual'的唯一标识符。 – AKSW

回答

1

无法将字面值作为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:prepdbp: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三倍那么确实...

+1

由于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) }'这是有风险的。 –

+0

啊,谢谢你让我知道还有其他有用的方法,比如'ENCODE_FOR_URI' - 我从来没有使用过这种方法,但是对于长字符串,这可能就是你冒险的意思吗? – AKSW

+0

非常感谢!它现在都在工作:) –