Question

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?

Was it helpful?

Solution

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:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top