1

I have an RDF file and I need to extract some information from it in a single line.

Now, I'm using AllegroGraph with Prolog query engin :

(select (?result)
      (q ?a !rdfs:label ?alabel)
      (q ?b !rdfs:label ?blabel)
      (lisp ?result (string+ ?alabel " AND " ?blabel))) 

to get the results in a single line:

 "{a1} AND {b1}" 
 "{a1} AND {b2}" 
 "{a2} AND {b1}" 
 "{a2} AND {b2}" 

Now, I need to group all the rows of ?result in a single line with the string "OR". so i get:

 "{a1} AND {b1} OR {a1} AND {b2} OR {a2} AND {b1} OR {a2} AND {b2}" 

Is there any function in prolog to do this?

user2598997
  • 287
  • 1
  • 2
  • 12
  • I don't know whether you can do this in AllegroGraph's Prolog or not, but this can be done relatively easily with a SPARQL 1.1 query. (This doesn't answer your question, but I expect that AllegroGraph supports SPARQL 1.1, so you can probably get this result with AllegroGraph, whether in Prolog or not.) – Joshua Taylor Sep 20 '13 at 17:04
  • Thank you. Actually i could'nt find a way to do it in prolog. I guess i will have to get back to SPARQL for the whole project. Can you explain how to do it in SPARQL please. – user2598997 Sep 27 '13 at 13:32
  • Sorry to hear that you didn't find a solution in the Prolog, but now you've got a SPARQL based answer. – Joshua Taylor Sep 27 '13 at 13:59

1 Answers1

2

The fact that you've only got a* on the left and b* on the right means that you've got some other selection condition than just having a label. Given data like this:

@prefix : <http://example.org/>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

:a1 a :ClassA ; rdfs:label "a1" .
:a2 a :ClassA ; rdfs:label "a2" .
:b1 a :ClassB ; rdfs:label "b1" .
:b2 a :ClassB ; rdfs:label "b2" .

you can select ?a and ?b by their classes (:ClassA and :ClassB), and then extract their labels as well, with a pattern like:

?a a :ClassA ; rdfs:label ?alabel .
?b a :ClassB ; rdfs:label ?blabel .

Then you can get the {alabel} AND {blabel} with a bind and a concat:

bind( concat( "{", ?alabel, "} AND {", ?blabel, "}" ) as ?AandB )

Using these, a query like

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?AandB { 
 ?a a :ClassA ; rdfs:label ?alabel .
 ?b a :ClassB ; rdfs:label ?blabel .
 bind( concat( "{", ?alabel, "} AND {", ?blabel, "}" ) as ?AandB )
}

will get you the kind of results that you can already get:

-------------------
| AandB           |
===================
| "{a2} AND {b2}" |
| "{a2} AND {b1}" |
| "{a1} AND {b2}" |
| "{a1} AND {b1}" |
-------------------

The trick now is to use group_concat and an implicit group to combine all these into a string, with a separator of " OR ":

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ( group_concat( ?AandB ; separator=" OR ") as ?string ) where { 
 ?a a :ClassA ; rdfs:label ?alabel .
 ?b a :ClassB ; rdfs:label ?blabel .
 bind( concat( "{", ?alabel, "} AND {", ?blabel, "}" ) as ?AandB )
}

to get a result:

----------------------------------------------------------------------
| string                                                             |
======================================================================
| "{a2} AND {b2} OR {a2} AND {b1} OR {a1} AND {b2} OR {a1} AND {b1}" |
----------------------------------------------------------------------

If you like, you can even get rid of the bind, and just put the concat expression right into the group_concat. You might find that easier to read (less jumping around) or harder to read (big one-liner), but at least it's good to have options:

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ( group_concat( concat( "{",?alabel,"} AND {",?blabel,"}" ) ; separator=" OR ") as ?string ) where { 
 ?a a :ClassA ; rdfs:label ?alabel .
 ?b a :ClassB ; rdfs:label ?blabel .
}

There are some other examples of group_concat floating around on StackOverflow that might be useful to you as well:

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353