如何在SPARQL中的单个CONSTRUCT查询中使用条件。

huangapple go评论53阅读模式
英文:

How to use conditions within a single CONSTRUCT query in SPARQL

问题

我想以编程方式构建一个rdf(实际上是owl)图,根据一些数据。数据可以是不同的'类型',根据类型,图应该具有不同的结构。数据存储在一个Excel电子表格中,包含多个工作表(每个工作表对应一个'类型')。

我希望天真地使用OntoText Refine一次读取所有工作表,并使用单个CONSTRUCT/INSERT sparql查询构建图,希望如果一个工作表中缺少用于绑定操作数的列,那么CONSTRUCT范围中的相关三元组会被跳过(当然)这不起作用(也许是因为空值不总是三元组的主语,我不确定)。

然后,我设想的另一种可能性是编写一些语言的脚本,该脚本可以读取Excel文件,并针对每个工作表运行不同的CONSTRUCT查询。这将起作用,但我更愿意出于简单性/可移植性的原因使用单个CONSTRUCT查询。

因此,我想编写以下查询,其中IF...THEN...部分是伪代码,用于表示我的意图,preferred_label等是工作表列:

BASE <http://www.mybaseprefix.com/>
PREFIX mapper: <http://www.ontotext.com/mapper/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

CONSTRUCT 
{

    ## constant part
    ?key_iri skos:prefLabel ?preferred_label


    ## variable part
    # case 1
    IF (NOT(?input = 'Input is null')) THEN {
        ?key_iri rdfs:subClassOf [ a owl:Restriction ;
        			owl:onProperty <has_input> ;
             			owl:allValuesFrom ?input ]. }
    
    # case 2
    IF (NOT(?output = 'Output is null')) THEN {
        ?key_iri rdfs:subClassOf [ a owl:Restriction ;
        		        owl:onProperty <has_output> ;
             			owl:allValuesFrom ?output ]. }
    
    } 
WHERE {
    SERVICE <http://localhost:7333/repositories/ontorefine:my_ontotext_refine_project> {
        ## key and key preferred label
        (?row_index "toTitlecase(replace(trim(cells["preferred_label"].value), ' ', '_'))") mapper:grel ?key_grel .
        BIND(IRI(mapper:encode_iri(?key_grel)) as ?key_iri)
        BIND(STRLANG(?spreadsheet_column_containing_preferred_label, "it") as ?preferred_label)

       
        ## object properties which can be sometimes null
        (?row_index "toTitlecase(replace(if(cells["input"].value == null, 'Input is null', cells["input"].value), ' ', '_'))") mapper:grel ?input_grel .
        BIND(IRI(mapper:encode_iri(?input_grel)) as ?input)
        (?row_index "toTitlecase(replace(if(cells["output"].value == null, 'Output is null', cells["output"].value), ' ', '_'))") mapper:grel ?output_grel .
        BIND(IRI(mapper:encode_iri(?output_grel)) as ?output)
        
    }
}

但我不确定如何(以及是否)可以实现这一点。
我了解到可以在WHERE范围内使用OPTIONAL模式匹配或IF函数(就像类似的stackoverflow问题中的答案建议的那样),但我想根据条件构建不同的图,而不是在发生某种条件时构建相同的图。

我将非常乐意接受建议。非常感谢。

英文:

I would like to programmatically construct an rdf (actually owl) graph given some data. The data can be of different 'types' and, depending on the type, the graph should have a different structure. The data is stored in an Excel spredsheet with multiple sheets (one sheet per 'type').

I hoped, naively, to use OntoText Refine to read all sheets at once and use a single CONSTRUCT/INSERT sparql query to build the graph, hoping that, if a column used in the binding operands were missing from a sheet, the relative triples in the CONSTRUCT scope would have been somehow skipped. (Of course) this is does not work (maybe because the null values are not always triple subjects, I'm not sure).

Then, another possibility I envisioned is to write a script in some language that could read the Excel file and, for each sheet, run a different CONSTRUCT query. This would work, but I would prefer to use a single CONSTRUCT query for simplicity/portability.

Therefore, I would like to write a query such as the following, where the IF...THEN... part is pseudocode to indicate my intention and preferred_label, etc. are sheets columns:

BASE &lt;http://www.mybaseprefix.com/&gt;
PREFIX mapper: &lt;http://www.ontotext.com/mapper/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX skos: &lt;http://www.w3.org/2004/02/skos/core#&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;
PREFIX owl: &lt;http://www.w3.org/2002/07/owl#&gt;
PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;

CONSTRUCT 
{

    ## constant part
    ?key_iri skos:prefLabel ?preferred_label


    ## variable part
    # case 1
    IF (NOT(?input = &#39;Input is null&#39;)) THEN {
        ?key_iri rdfs:subClassOf [ a owl:Restriction ;
        			owl:onProperty &lt;has_input&gt; ;
             			owl:allValuesFrom ?input ]. }
    
    # case 2
    IF (NOT(?output = &#39;Output is null&#39;)) THEN {
        ?key_iri rdfs:subClassOf [ a owl:Restriction ;
        		        owl:onProperty &lt;has_output&gt; ;
             			owl:allValuesFrom ?output ]. }
    
    } 
WHERE {
    SERVICE &lt;http://localhost:7333/repositories/ontorefine:my_ontotext_refine_project&gt; {
        ## key and key preferred label
        (?row_index &quot;toTitlecase(replace(trim(cells[\&quot;preferred_label\&quot;].value), &#39; &#39;, &#39;_&#39;))&quot;) mapper:grel ?key_grel .
        BIND(IRI(mapper:encode_iri(?key_grel)) as ?key_iri)
        BIND(STRLANG(?spreadsheet_column_containing_preferred_label, &quot;it&quot;) as ?preferred_label)

       
        ## object properties which can be sometimes null
        (?row_index &quot;toTitlecase(replace(if(cells[\&quot;input\&quot;].value == null, &#39;Input is null&#39;, cells[\&quot;input\&quot;].value), &#39; &#39;, &#39;_&#39;))&quot;) mapper:grel ?input_grel .
        BIND(IRI(mapper:encode_iri(?input_grel)) as ?input)
        (?row_index &quot;toTitlecase(replace(if(cells[\&quot;output\&quot;].value == null, &#39;Output is null&#39;, cells[\&quot;output\&quot;].value), &#39; &#39;, &#39;_&#39;))&quot;) mapper:grel ?output_grel .
        BIND(IRI(mapper:encode_iri(?output_grel)) as ?output)
        
    }
}

But I am not sure how (and if) is possible to do this.
I understand that I can use OPTIONAL pattern matching or IF functions in the WHERE scope (like answers in similar stackoverflow questions suggested), but I want to build different graphs given a condition not the same graph if a certain condition occurs.

I would gladly accept suggestions. Many thanks.

答案1

得分: 0

经过一些调试,我意识到我的问题可以在WHERE范围中使用OPTIONAL子句来部分解答。
首先,需要删除方括号和圆括号的语法糖。

例如,从

 ?key_iri rdfs:subClassOf [ a owl:Restriction ;
                    owl:onProperty &lt;has_input&gt; ;
                    owl:allValuesFrom ?input ]

改为

 ?key_iri rdfs:subClassOf ?new_blank_node .
 ?new_blank_node a owl:Restriction ;
                   owl:onProperty &lt;has_input&gt; ;
                   owl:allValuesFrom ?input .

并且,如果圆括号中存在RDF列表,则必须使用明确的空白节点进行替换。

然后,可以在WHERE范围中添加类似以下内容:

OPTIONAL {  FILTER(?input != &#39;Input is null&#39;)
      			BIND(BNODE() as ?new_blank_node)}

不过,这并不是理想的解决方法,因为复杂的OWL模式可能需要长时间的努力以及更复杂的过滤器,以及在OPTIONAL范围内使用多个空白节点才能达到所需的行为。

我选择这个答案,希望它将来能帮助其他人。
祝好。

英文:

After some tinkering, I realized that my problem can be answered, albeit partially, by using OPTIONAL clauses in the WHERE scope.
First of all, it is necessary to remove the syntactical sugar of the square and round brackets.

E.g. from

 ?key_iri rdfs:subClassOf [ a owl:Restriction ;
                    owl:onProperty &lt;has_input&gt; ;
                    owl:allValuesFrom ?input ]

to

 ?key_iri rdfs:subClassOf ?new_blank_node .
 ?new_blank_node a owl:Restriction ;
                   owl:onProperty &lt;has_input&gt; ;
                   owl:allValuesFrom ?input .

And, similarly, if rdf lists are present with round brackets, they must be replaced using explicitly blank nodes.

Then, one can add in the WHERE scope something like:

OPTIONAL {  FILTER(?input != &#39;Input is null&#39;)
      			BIND(BNODE() as ?new_blank_node)}

This is not ideal, though, as complex OWL patterns may require lengthy effort and more complex filters as well as several blank nodes within the OPTIONAL scopes to reach the desired behaviour.

I select this answer hoping that It may help somebody else in the future.
Regards.

huangapple
  • 本文由 发表于 2023年6月1日 22:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383019.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定