Matching optional triples without using OPTIONAL

2019-09-02 03:23发布

I want to query records where not all records have all properties. Is it possible to get them with blank values by just using basic graph patterns in the query and without using optional?

标签: sparql
2条回答
虎瘦雄心在
2楼-- · 2019-09-02 04:00

A variable has to be bound to some value in order for there to be a match. The exception is with optional. There you can get a match where it's optional for a particular pattern to have matched. If you want an optional variable for a match, you'll have to use optional.

Technically, you could avoid using optional by using a union with the different partial matchings that could occur. In that sense, you wouldn't be using optional, but it'd be even more complex:

@prefix : <urn:ex:>.

:a :hasName "Person A".

:b :hasAge 32 .

:c :hasName "Person C" ;
   :hasAge 71 .
prefix : <urn:ex:>

select * where {
  #-- ?age but no name
  { ?person :hasAge ?age
    filter not exists { ?person :hasName ?name }}
  union
  #-- ?name but no age
  { ?person :hasName ?name
    filter not exists { ?person :hasAge ?age }}
  union
  #-- ?name and ?age
  { ?person :hasName ?name ; :hasAge ?age }
}
-----------------------------
| person | age | name       |
=============================
| :a     |     | "Person A" |
| :b     | 32  |            |
| :c     | 71  | "Person C" |
-----------------------------
查看更多
倾城 Initia
3楼-- · 2019-09-02 04:14

You can achieve this by using a CONSTRUCT query. Use a CONSTRUCT with a simple BGP to retrieve the relevant subset of your complete dataset, and then post-process that result.

For example, imagine you have a set of records about persons, where there are names, e-mail addresses, phone numbers, but not necessarily all of these properties are filled out for every person.

You can then just do a query that retrieves all properties for resources of type Person. Here's an example in Java (using Sesame API):

// query to retrieve all properties of things of type Person
String queryString = "CONSTRUCT WHERE {?s a <urn:Person>; ?p ?o }";
GraphQuery query = conn.prepareGraphQuery(SPARQL, queryString);
Model result = QueryResults.asModel(query.evaluate());

You now have a query result that contains all available person-data. Dealing with potentially missing values is now just a question of processing the result. For example:

for (Resource person: result.subjects()) {
   Literal name = result.filter(person, FOAF.NAME, null).objectLiteral(); 
   if (name == null) {
       System.out.println("name is missing!");
   }
   else {
       ...
   }
}
查看更多
登录 后发表回答