4
$\begingroup$

I would like to match triplets from two graphs in a RDFStores on the string value of one containing the string value of the other. To test this I made the following store with named graphs by using some code from the documentation.

Needs["GraphStore`"]

foaf[s_] := IRI["http://xmlns.com/foaf/0.1/" <> s];

store =
 RDFStore[{},
  <|foaf["people"] -> {
     RDFTriple[RDFBlankNode["a"], foaf["firstName"], "Till"],
     RDFTriple[RDFBlankNode["a"], foaf["surname"], "Schneider"],
     RDFTriple[RDFBlankNode["b"], foaf["firstName"], "Eva"],
     RDFTriple[RDFBlankNode["b"], foaf["surname"], "Baumgärtner"]
     },
   foaf["streets"] -> {
     RDFTriple[RDFBlankNode["s"], foaf["name"], "Wide Street"],
     RDFTriple[RDFBlankNode["s"], foaf["city"], "Narrows Village"],
     RDFTriple[RDFBlankNode["t"], foaf["name"], "Tillers Ave"],
     RDFTriple[RDFBlankNode["t"], foaf["city"], "Fisher Town"]
     }
   |>]

Mathematica graphics

Using SPARQLSelect and SPARQLEvaluation I can query each from each graph individually.

SPARQLSelect[
  {
     SPARQLGraph[
      foaf["people"],
      RDFTriple[SPARQLVariable["person"], foaf["firstName"], 
       SPARQLVariable["personFirstName"]]
      ]
     } /; SPARQLEvaluation["CONTAINS"][
     SPARQLVariable["personFirstName"],
     "Til"
     ] -> {"person"}
  ][store]
{<|"person" -> RDFBlankNode["a"]|>}

and

SPARQLSelect[
  {
     SPARQLGraph[
      foaf["streets"],
      RDFTriple[SPARQLVariable["street"], foaf["name"], 
       SPARQLVariable["streetName"]]
      ]
     } /; SPARQLEvaluation["CONTAINS"][
     SPARQLVariable["streetName"],
     "Til"
     ] -> {"street"}
  ][store]
{<|"street" -> RDFBlankNode["t"]|>}

However I do not get any result back when I try to query both graphs together using a filter on variables from each. I am expecting to get the "a" item in foaf["people"] and the "t" item in foaf["streets"].

SPARQLSelect[
  {
     SPARQLGraph[
      foaf["people"],
      RDFTriple[SPARQLVariable["person"], foaf["firstName"], 
       SPARQLVariable["personFirstName"]]
      ],
     SPARQLGraph[
      foaf["streets"],
      RDFTriple[SPARQLVariable["street"], foaf["name"], 
       SPARQLVariable["streetName"]]
      ]
     } /; SPARQLEvaluation["CONTAINS"][
       SPARQLVariable["personFirstName"],
       SPARQLVariable["streetName"]
     ] -> {"person", "street"}
  ][store]
{}

The larger problem is along the lines of using SPARQL to query the "City" and "Airport" entities to find all airports that contain a city name, calculate the distance between the city and the airport, and select the "City" and "Airport" with the top 10 differences. The above is the first step to get there.

$\endgroup$
4
  • $\begingroup$ In your updated question, your query does not work because you have the order of arguments in the CONTAINS the wrong way around. Do SPARQLEvaluation["CONTAINS"][SPARQLVariable["streetName"], SPARQLVariable["personFirstName"]] like in my answer instead :) $\endgroup$
    – Carl Lange
    Commented Apr 30, 2019 at 22:13
  • $\begingroup$ @CarlLange Eureka!!!! $\endgroup$
    – Edmund
    Commented Apr 30, 2019 at 22:16
  • $\begingroup$ Congratulations on being the first to open a question about SPARQL by the way 🎉 $\endgroup$
    – Carl Lange
    Commented Apr 30, 2019 at 22:25
  • $\begingroup$ @CarlLange Thanks? Another one is coming soon. :-) $\endgroup$
    – Edmund
    Commented Apr 30, 2019 at 22:26

1 Answer 1

2
$\begingroup$

If you use named graphs, you can do the following:

data = RDFStore[{}, <|
   foaf["streets"] -> {RDFTriple[RDFBlankNode["s"], foaf["name"], 
      "Wide Street"], 
     RDFTriple[RDFBlankNode["s"], foaf["city"], "Narrows Village"], 
     RDFTriple[RDFBlankNode["t"], foaf["name"], "Tillers Ave"], 
     RDFTriple[RDFBlankNode["t"], foaf["city"], "Fisher Town"]},
   foaf["people"] -> {
     RDFTriple[RDFBlankNode["a"], foaf["firstName"], "Till"], 
     RDFTriple[RDFBlankNode["a"], foaf["surname"], "Schneider"], 
     RDFTriple[RDFBlankNode["b"], foaf["firstName"], "Eva"], 
     RDFTriple[RDFBlankNode["b"], foaf["surname"], "Baumgärtner"]
     }
   |>]

SPARQLSelect[{
     SPARQLGraph[foaf@"people",
      RDFTriple[SPARQLVariable["person"], foaf["firstName"], 
       SPARQLVariable["personFirstName"]]],
     SPARQLGraph[foaf@"streets",
      RDFTriple[SPARQLVariable["street"], foaf["name"], 
       SPARQLVariable["streetName"]]]} /; 
    SPARQLEvaluation["CONTAINS"][SPARQLVariable["streetName"], 
     SPARQLVariable["personFirstName"]] -> {"person", "street"}][data]

which returns {<|"person" -> RDFBlankNode["a"], "street" -> RDFBlankNode["t"]|>}.

This query is equivalent to:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT ?person ?street WHERE {
  GRAPH foaf:people {
    ?person foaf:firstName ?personFirstName .
  }
  GRAPH foaf:streets {
    ?street foaf:name ?streetName .
  }
  FILTER (CONTAINS(?streetName, ?personFirstName))
}

Otherwise, it's not clear to me that you can easily join or query across multiple RDFStores like that. Your query does work if you create a single RDFStore with all the triples:

data = RDFStore[
  {
   RDFTriple[RDFBlankNode["a"], foaf["firstName"], "Till"], 
   RDFTriple[RDFBlankNode["a"], foaf["surname"], "Schneider"], 
   RDFTriple[RDFBlankNode["b"], foaf["firstName"], "Eva"], 
   RDFTriple[RDFBlankNode["b"], foaf["surname"], "Baumgärtner"],
   RDFTriple[RDFBlankNode["s"], foaf["name"], "Wide Street"], 
   RDFTriple[RDFBlankNode["s"], foaf["city"], "Narrows Village"], 
   RDFTriple[RDFBlankNode["t"], foaf["name"], "Tillers Ave"], 
   RDFTriple[RDFBlankNode["t"], foaf["city"], "Fisher Town"]
   }
  ]

SPARQLSelect[{RDFTriple[SPARQLVariable["person"], foaf["firstName"], 
      SPARQLVariable["personFirstName"]], 
     RDFTriple[SPARQLVariable["street"], foaf["name"], 
      SPARQLVariable["streetName"]]} /; 
    SPARQLEvaluation["CONTAINS"][SPARQLVariable["streetName"], 
     SPARQLVariable["personFirstName"]] -> {"person", "street"}][data]

You can also express this join programatically:

SPARQLSelect[{RDFTriple[SPARQLVariable["person"], foaf["firstName"], 
      SPARQLVariable["personFirstName"]], 
     RDFTriple[SPARQLVariable["street"], foaf["name"], 
      SPARQLVariable["streetName"]]} /; 
    SPARQLEvaluation["CONTAINS"][SPARQLVariable["streetName"], 
     SPARQLVariable["personFirstName"]] -> {"person", "street"}][
 RDFStore[Join @@ {First@personData, First@streetData}]]

(eg, RDFStore[Join @@ {First@personData, First@streetData}])

$\endgroup$
8
  • $\begingroup$ Thanks for your answer but you are making the join in the Notebook. The graph stores are too big to bring them down into the notebook to perform a join. The join as to be in SPARQL on the server. $\endgroup$
    – Edmund
    Commented Apr 30, 2019 at 21:25
  • $\begingroup$ I see - that wasn't clear in your question. I don't know that the built-in SPARQL functionality can actually use out-of-core data in this way. Can you point to an example in the documentation? $\endgroup$
    – Carl Lange
    Commented Apr 30, 2019 at 21:28
  • $\begingroup$ Or in fact an example of how you would do this normally, ignoring Wolfram Language (please add it to your question). $\endgroup$
    – Carl Lange
    Commented Apr 30, 2019 at 21:35
  • $\begingroup$ I think I have figured out part of it; the named store with streetData = RDFStore[{}, <|foaf["streets"] -> { RDFTriple[RDFBlankNode["s"], foaf["name"], "Wide Street"], RDFTriple[RDFBlankNode["s"], foaf["city"], "Narrows Village"], RDFTriple[RDFBlankNode["t"], foaf["name"], "Tillers Ave"], RDFTriple[RDFBlankNode["t"], foaf["city"], "Fisher Town"] } |>] $\endgroup$
    – Edmund
    Commented Apr 30, 2019 at 21:35
  • $\begingroup$ However, the SPARQLSelect in the OP is still not working. $\endgroup$
    – Edmund
    Commented Apr 30, 2019 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.