问题
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?
回答1:
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:
- Aggregating results from SPARQL query
- RDF list subjects with their objects in a single line (this is actually another question that you asked, and that I answered, and in that answer, I also pointed out the previous question)
- obtain the matrix in protege (this does some pretty fancy string manipulation)
- SPARQL query to get all parent of a node
来源:https://stackoverflow.com/questions/18917053/can-i-do-this-in-allegrograph-prolog