Iterate over nodes and fetch rdf data using a specific property on each node

I used the neosemantics plugin to import all instances of cities located in Italy. I also imported all instances of points of interest located in Italy. Now, I want to add a relationship to show which points of interest are in which cities.

To do this, I'm trying to iterate through all the City nodes and for each node, use its uri to find all the points of interest in that city. This is the query I tested in https://query.wikidata.org/ using the uri for Florence (wd:Q2044)

SELECT DISTINCT ?attraction ?attractionLabel ?streetAddress ?country

WHERE {
    ?attraction (wdt:P31/wdt:P279*) wd:Q570116;
        rdfs:label ?attractionLabel.
    ?attraction wdt:P131 wd:Q2044 .
    FILTER(LANG(?attractionLabel) = "en")
}

I'm having trouble converting this to Cypher in neo4J Desktop. I tried converting ?attraction wdt:P131 wd:Q2044 to filter (?attraction wdt:P131 c.uri), but it's returning 0 triples. Has anyone who's done this before give me some pointers?

MATCH (c:City)
WITH ' PREFIX sch: <http://schema.org/> 
CONSTRUCT{ ?item a sch:City;
			   sch:attraction ?attraction.
		        ?attraction a sch:Attraction;
           	           sch:city ?item. } 
WHERE { ?attraction (wdt:P31/wdt:P279*) wd:Q960648 .
        filter (?attraction wdt:P131 c.uri)
        ?attraction rdfs:label ?attractionName . 
          filter(lang(?attractionName) = "en") 
 } ' AS sparql CALL n10s.rdf.import.fetch(
  "https://query.wikidata.org/sparql?query=" +  
      apoc.text.urlencode(sparql),"JSON-LD", 
    { headerParams: { Accept: "application/ld+json"} ,   
      handleVocabUris: "IGNORE"})
YIELD terminationStatus, triplesLoaded
RETURN terminationStatus, triplesLoaded

Hi,

I have not tried it yet but I will test with:

MATCH (c:City)
WITH ' PREFIX sch: <http://schema.org/> 
CONSTRUCT{ ?item a sch:City;
			   sch:attraction ?attraction.
		        ?attraction a sch:Attraction;
           	           sch:city ?item. } 
WHERE { ?attraction (wdt:P31/wdt:P279*) wd:Q960648 .
        filter (?attraction wdt:P131 c.uri)
        ?attraction rdfs:label ?attractionName . 
          filter(lang(?attractionName) = "en") 
 } ' AS sparql
CALL n10s.rdf.import.fetch("https://query.wikidata.org/sparql","JSON-LD", {
  handleVocabUris: "IGNORE",
  headerParams: { Accept: "application/ld+json"},
  payload: "query=" + apoc.text.urlencode(sparql),   
    handleVocabUris: "IGNORE"
})
yield triplesLoaded
return triplesLoaded

It should produce the same result but this is the way documented in thte wiki.

BR. Paul

You're right, it unfortunately produces the same result with 0 triples fetched. I looked at this Medium article and updated my query as follows:

MATCH (c:City)
WITH ' PREFIX sch: <http://schema.org/> 
CONSTRUCT{ ?item a sch:City;
			   sch:attraction ?attraction.
		        ?attraction a sch:Attraction;
           	           sch:city ?item. } 
WHERE { 
		?attraction (wdt:P31/wdt:P279*) wd:Q960648 .
        ?attraction wdt:P131 <' + c.uri + '> .
        ?attraction rdfs:label ?attractionName . 
          filter(lang(?attractionName) = "en") 
 } ' AS sparql CALL n10s.rdf.import.fetch(
  "https://query.wikidata.org/sparql?query=" +  
      apoc.text.urlencode(sparql),"JSON-LD", 
    { headerParams: { Accept: "application/ld+json"} ,   
      handleVocabUris: "IGNORE"})
YIELD terminationStatus, triplesLoaded
RETURN terminationStatus, triplesLoaded

This returned a terminationStatus of OK for each city entity and showed that triples were loaded, but it didn't have the effect I wanted. It seems to have overwritten some of the resources already in the db. For example, the Attraction nodes previously had the following properties: id, wikipedia image link (optional), wiki article, geo location, name, and uri. Now some of the nodes only have the id and uri. In addition, the attraction nodes had relationships with another resource Type (i.e. museum, monument, garden) but now that relationship is gone, and I still don't see a relationship between city and attraction.

I found interesting information about the Wikidata SPARQL endpoint and linked data fragments endpoint here: https://www.mediawiki.org/wiki/Wikidata_Query_Service/User_Manual#SPARQL_endpoint

To verify the endpoint usage I put your SPARQL query in Postman and successfully got the result:

I tried to formats, "xml" and "json". The xml output was a valid RDF file. I don't know if the json output is JSON-LD conform. Could be tested.

Then I tried the same with the n10s.rdf.import.fetch stored procedure and got no results back.

The next step was to use the example describe in the neosemantics wiki: https://neo4j.com/docs/labs/nsmntx/current/import/#advancedfetching

This example is working.

I think either is a configuration problem with the Wikidata API and formats or a bug.

Thanks for the help! I managed to import the cities by altering the cypher query in the section titled " Dynamically extend the Knowledge Graph" from Dr. Barassa's blog post here. Adding it here in case it's useful to anyone else in the future:

MATCH (attraction:PointOfInterest) 
WITH 'PREFIX sch: <http://schema.org/> 
CONSTRUCT { ?city a sch:City ; 
sch:containsPlace ?attraction ; 
rdfs:label ?cityName  } 
WHERE { ?attraction wdt:P131 ?city . 
filter(?attraction = <' + attraction.uri +'>) 
?city rdfs:label 
?cityName . 
filter (lang(?cityName) = "en") }' AS city_sparql, 
attraction CALL n10s.rdf.import.fetch("https://query.wikidata.org/sparql?query=" + 
apoc.text.urlencode(city_sparql),"JSON-LD", 
{ headerParams: { Accept: "application/ld+json"} , 
handleVocabUris: "IGNORE"}) 
YIELD terminationStatus, triplesLoaded 
RETURN attraction.name, terminationStatus, triplesLoaded
1 Like