Find individuals in SPARQL based on other relations / Compare sets

时光毁灭记忆、已成空白 提交于 2019-12-11 11:19:12

问题


Given are Objects :A, :B and :C which have properties assigned, whereas these properties are not scalar themselves but are also objects with key and value properties.

@prefix x: <http://example.com/example#> 

x:A x:hasProp x:Prop1 .
x:Prop1 x:Key "1" .
x:Prop1 x:Value "AA" .
x:B x:hasProp x:Prop2 .
x:Prop2 x:Key "1" .
x:Prop2 x:Value "AA" .
x:C x:hasProp x:Prop3 .
x:C x:hasProp x:Prop4 .
x:Prop3 x:Key "1" .
x:Prop3 x:Value "AA" .
x:Prop4 x:Key "2" .
x:Prop4 x:Value "BB" .

How can I assert that :A and :B have the same properties whereas :A and :C not? I'm new to SPARQL and I have no idea... I tried something like :

prefix x: <http://example.com/example#> 

select ?another ?k ?v
{x:A x:hasProp ?p .
?p ?k ?v .
?another x:hasProp ?p2 .   
?p2 ?k ?v .
}

but I think it's a wrong way. It also returns :C.

How can one easily compare two sets in SPARQL?


Additional question: The query from the answer 1 works fine but only if :A used directly. Using a variable in place of :A makes :C also to qualify. Why?

I mean: insert some condition to find :A

prefix : <http://example.com/example#> 

INSERT DATA {:A rdfs:label "A"}

and then use a variable in place of :A

prefix : <http://example.com/example#> 

select ?other ?k ?v {
  #-- Find ?other such that :A and ?other have
  #-- some property in common,
  ?a rdfs:label "A"
  ?a     :hasProp [ :Key ?k ; :Value ?v ] .
  ?other :hasProp [ :Key ?k ; :Value ?v ] .

  #-- but remove any ?other such that:
  filter not exists { 
#-- (i) :A has a property that ?other doesn't; 
  {
    ?a :hasProp [ :Key ?kk ; :Value ?vv ] .
    filter not exists { ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
     }
  }
  union
  #-- or (ii) ?other has a property that :A doesn't.
  {
    ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
    filter not exists {
         ?a :hasProp [ :Key ?kk ; :Value ?vv ] .
   }
 }
}  
}

Update:

prefix : <http://example.com/example#> 

INSERT DATA {
:A rdfs:label "A" .
:A :hasProp :Prop1 .
:Prop1 :Key "1" .
:Prop1 :Value "AA" .

:B :hasProp :Prop2 .
:Prop2 :Key "1" .
:Prop2 :Value "AA" .

:C :hasProp :Prop3 .
:C :hasProp :Prop4 .
:Prop3 :Key "1" .
:Prop3 :Value "AA" .

:Prop4 :Key "2" .
:Prop4 :Value "BB" .
}

Query using :A

prefix : <http://example.com/example#> 

select ?other ?k ?v {
   :A    :hasProp [ :Key ?k ; :Value ?v ] .
   ?other :hasProp [ :Key ?k ; :Value ?v ] .
   filter not exists { 
     { :A :hasProp [ :Key ?kk ; :Value ?vv ] .
       filter not exists { ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
       }
     }
     union
     {
      ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists { :A :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
   }
  }
 }

Answer:

 -------------------  
 |other|  k  | v  
 |A    | "1" | "AA"  
 |B    | "1" | "AA"  
 -------------------  

Query using variable ?a:

 prefix : <http://example.com/example#> 

select ?other ?k ?v {
   ?a rdfs:label "A" .
   ?a    :hasProp [ :Key ?k ; :Value ?v ] .
   ?other :hasProp [ :Key ?k ; :Value ?v ] .
   filter not exists { 
     { ?a :hasProp [ :Key ?kk ; :Value ?vv ] .
       filter not exists { ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
       }
     }
     union
     {
      ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists { ?a :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
    }
   }
 }

returns

other k v
A "1" "AA"
B "1" "AA"
C "1" "AA"


回答1:


Why your query doesn't return what you want…

It always helps to show the output that you're actually getting, because then you can point out which parts you're not expecting. In this case, your query returns:

---------------------------
| another | k      | v    |
===========================
| :C      | :Value | "AA" |
| :C      | :Key   | "1"  |
| :B      | :Value | "AA" |
| :B      | :Key   | "1"  |
| :A      | :Value | "AA" |
| :A      | :Key   | "1"  |
---------------------------

This makes sense in your case because C does have the kind of data you're asking about. It's this portion of your data:

x:A x:hasProp x:Prop1 .
x:Prop1 x:Key "1" .
x:Prop1 x:Value "AA" .
…
x:C x:hasProp x:Prop3 .
…
x:Prop3 x:Key "1" .
x:Prop3 x:Value "AA" .

A query that returns what you want

Here's how I'd write a query that gets you what you want. It's easy enough to find things that have some property in common with :A. From those, you need to filter out any ?other such that either :A has a property that ?other doesn't, or such that ?other has a property that :A doesn't,

prefix : <http://example.com/example#> 

select ?other ?k ?v {
  #-- Find ?other such that :A and ?other have
  #-- some property in common,
  :A     :hasProp [ :Key ?k ; :Value ?v ] .
  ?other :hasProp [ :Key ?k ; :Value ?v ] .

  #-- but remove any ?other such that:
  filter not exists { 
    #-- (i) :A has a property that ?other doesn't; 
    {
      :A :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists {
        ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
    }
    union
    #-- or (ii) ?other has a property that :A doesn't.
    {
      ?other :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists {
        :A :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
    }
  }
}
----------------------
| other | k   | v    |
======================
| :B    | "1" | "AA" |
| :A    | "1" | "AA" |
----------------------

Enumerating the equivalence classes

In fact, you can use a generalization of this to list the different equivalence classes in the data.

prefix : <http://example.com/example#> 

select distinct ?x ?y {
  ?x :hasProp [] .
  ?y :hasProp [] .

  filter not exists { 
    {
      ?x :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists {
        ?y :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
    }
    union
    {
      ?y :hasProp [ :Key ?kk ; :Value ?vv ] .
      filter not exists {
        ?x :hasProp [ :Key ?kk ; :Value ?vv ] .
      }
    }
  }
}
order by ?x ?y
-----------
| x  | y  |
===========
| :A | :A |
| :A | :B |
| :B | :A |
| :B | :B |
| :C | :C |
-----------


来源:https://stackoverflow.com/questions/24713925/find-individuals-in-sparql-based-on-other-relations-compare-sets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!