How to return a single foaf:name?

人盡茶涼 提交于 2019-12-24 02:32:03

问题


I have the following DBpedia SPARQL that shows philosophers that influenced philosophers. However, it returns duplicates when the philosopher has more than one foaf:name:

SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName .
}

SPARQL results

How can I return a single name if there are multiple values for ?name and ?includedName. I would be happy with the first one, or the least number of characters to pick which to keep.

Here is another example for just Plato influencing Bertrand Russell. I would like this to return one row, but I get four:

SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name , "Plato"@en .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName, "Bertrand Arthur William Russell, 3rd Earl Russell"@en .
}

SPARQL results


回答1:


The Queries

It sounds like you want a query something like:

SELECT ?philosopher ?pName ?influence (SAMPLE(?iName) as ?iName)
WHERE {
  # This subquery selects all the philosophers and
  # selects just one of their names . 
  {
    SELECT ?philosopher (SAMPLE(?pName) as ?pName) WHERE {
      ?philosopher a dbpedia-owl:Philosopher ;
                   foaf:name ?pName .
    }
    GROUP BY ?philosopher
  }

  # This main query selects the influence of the 
  # philosophers and select their names.  The GROUP
  # BY on the outer query puts all the
  # (?philosopher,?pName,?influence,?iName) tuples 
  # that have the same ?philosopher, ?pName, and 
  # influence together, and the (SAMPLE(?iName) as ?iName)
  # in the outer SELECT combines them all, choosing an 
  # arbitrary representative ?iName.
  ?influence dbpedia-owl:influenced ?philosopher ;
             a dbpedia-owl:Philosopher ;
             foaf:name ?iName .
}
GROUP BY ?philosopher ?pName ?influence

SPARQL results

If you are only interested in the names, and do not care about selecting the actual resources, you do not need ?philosopher and ?influence in the outermost SELECT and can make it

SELECT ?pName (SAMPLE(?iName) as ?iName)
WHERE { …

SPARQL results

You also might want to add an ORDER BY at the end to make the results a little bit easier to check:

…
GROUP BY ?philosopher ?pName ?influence
ORDER BY ?pName

SPARQL results

These last results include, for Plato, the following rows:

"Plato"@en  "Socrates"@en
"Plato"@en  "Parmenides"@en
"Plato"@en  "Zeno of Elea"@en
"Plato"@en  "Pythagoras"@en
"Plato"@en  "Gorgias"@en
"Plato"@en  "Protagoras"@en
"Plato"@en  "Heraclitus"@en

In the query I've written here, I've used SAMPLE to pick one of the foaf:names of a philosopher arbitrarily, but there are other functions in the aggregate algebra that you can use to select a value. Min might be interest to you if you want the ‘first‘ value in order.

Subqueries, GROUP BY, and SAMPLE, MIN, etc.

This is actually very similar to the example given for subqueries in Section 12, Subqueries of the SPARQL specification. In that example, the following query is used to select the people that Alice knows, and for each one, select just one of the names of the people:

PREFIX : <http://people.example/>
SELECT ?y ?minName
WHERE {
  :alice :knows ?y .
  {
    SELECT ?y (MIN(?name) AS ?minName)
    WHERE {
      ?y :name ?name .
    } GROUP BY ?y
  }
}

This was not to hard to adapt for the philosophical influence problem. The philosophers problem began by selecting all the philosophers and their names, grouping by the actual philosopher resource, and picking a representative name for each philosopher using sample. The outer query does the same, but rather than selecting philosophers, it is selecting the entities that influenced each philosopher. The results are grouped and a representative name for the influence is selected.




回答2:


I have determined how I want to select the unique name for a philosopher, see sparql below that returns one name for each philosopher.

However, I don't see a why to incorporate this in the larger query that returns a name both for philosopher and for influenced philosopher without running this code once for each philosopher which would be a large and unwieldy query. My sense is that my code will be more readable if I run the philosopher names and the influensed by queries separatly and look up the names in code rather than sparql. Perhaps I am missing some sparql feature that will make this easy. Please Advice

Here is the description of how I am getting unique names:

Get all names for a Philosopher from foaf:names and dbprop:names Filter to include only names that contain at least one Latin letter character ( A-Z ) Find the length of the shortest names Pick the minimum of all of the names that are shortest

PREFIX dbpedia: <http://dbpedia.org/>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpprop: <http://dbpedia.org/property/>

SELECT ?philosopher (min(?name) as ?minName)
WHERE {{
   ?philosopher foaf:name ?name        .
  } UNION {
   ?philosopher dbpprop:name ?name     .
  }
  FILTER( strlen(?name) = ?minLength )   .  # get the shortest names
  FILTER( REGEX( str(?name) , "[A-Z]" )) .  # exlude names with no latin charachters
  {
    SELECT ?philosopher (min(strlen(?name)) as ?minLength)
    WHERE {{
      ?philosopher a  dbpedia-owl:Philosopher ;
         foaf:name ?name .
    } UNION {
      ?philosopher a  dbpedia-owl:Philosopher ;
         dbpprop:name ?name .
    }
    FILTER( REGEX( str(?name) , "[A-Z]" )) .
    }
    GROUP BY ?philosopher
  }
}
GROUP BY ?philosopher
ORDER BY ?philosopher


来源:https://stackoverflow.com/questions/17129225/how-to-return-a-single-foafname

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