-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gravsearch enhancements and fixes #870
Conversation
- Require the match function to be the top-level expression in a FILTER. - Rename things to use the name Gravsearch.
@tobiasschweizer I made some changes to If you run PREFIX knora-api: <http://api.knora.org/ontology/knora-api/simple/v2#>
PREFIX anything: <http://0.0.0.0:3333/ontology/0001/anything/simple/v2#>
CONSTRUCT {
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> knora-api:isMainResource true .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> a anything:Thing .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> anything:hasText ?text .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> anything:hasInteger ?integer .
} WHERE {
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> a knora-api:Resource .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> a anything:Thing .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> anything:hasText ?text .
anything:hasText knora-api:objectType xsd:string .
?text a xsd:string .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> anything:hasInteger ?integer .
anything:hasInteger knora-api:objectType xsd:integer .
?integer a xsd:integer.
} This is the prequery: SELECT DISTINCT (GROUP_CONCAT(?integer; SEPARATOR='') AS ?integerConcat) (GROUP_CONCAT(?text; SEPARATOR='') AS ?textConcat)
WHERE {
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/0001/anything#Thing> .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.knora.org/ontology/0001/anything#hasText> ?text .
GRAPH <http://www.ontotext.com/explicit> {
?text <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.knora.org/ontology/0001/anything#hasInteger> ?integer .
GRAPH <http://www.ontotext.com/explicit> {
?integer <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
}
OFFSET 0
LIMIT 25 This is the prequery result: {
"head":{
"vars":[
"integerConcat",
"textConcat"
]
},
"results":{
"bindings":[
{
"integerConcat":{
"type":"literal",
"value":"http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg"
},
"textConcat":{
"type":"literal",
"value":"http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ"
}
}
]
}
} This is the main query: CONSTRUCT {
?mainResourceVar <http://www.knora.org/ontology/knora-base#isMainResource> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> .
?mainAndDependentResource <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
?mainAndDependentResource ?mainAndDependentResourceProp ?mainAndDependentResourceObj .
?mainAndDependentResource <http://www.knora.org/ontology/knora-base#hasValue> ?mainAndDependentResourceValueObject .
?mainAndDependentResource ?mainAndDependentResourceValueProp ?mainAndDependentResourceValueObject .
?mainAndDependentResourceValueObject ?mainAndDependentResourceValueObjectProp ?mainAndDependentResourceValueObjectObj .
?mainAndDependentResourceValueObject <http://www.knora.org/ontology/knora-base#valueHasStandoff> ?standoffNode .
?standoffNode ?standoffProp ?standoffValue .
?mainAndDependentResourceValueObject <http://www.knora.org/ontology/knora-base#valueHasListNode> ?listNode .
?listNode <http://www.w3.org/2000/01/rdf-schema#label> ?listNodeLabel .
} WHERE {
{
VALUES ?mainResourceVar { <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> }
?mainResourceVar <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?mainResourceVar <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
} UNION {
VALUES ?mainAndDependentResource { <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> }
?mainAndDependentResource <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResource <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResource ?mainAndDependentResourceProp ?mainAndDependentResourceObj .
}
} UNION {
VALUES ?mainAndDependentResourceValueObject { <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> }
?mainAndDependentResource <http://www.knora.org/ontology/knora-base#hasValue> ?mainAndDependentResourceValueObject .
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResource ?mainAndDependentResourceValueProp ?mainAndDependentResourceValueObject .
}
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResourceValueObject <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResourceValueObject ?mainAndDependentResourceValueObjectProp ?mainAndDependentResourceValueObjectObj .
}
} UNION {
VALUES ?mainAndDependentResourceValueObject { <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> }
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResourceValueObject <http://www.knora.org/ontology/knora-base#valueHasStandoff> ?standoffNode .
}
GRAPH <http://www.ontotext.com/explicit> {
?standoffNode ?standoffProp ?standoffValue .
}
} UNION {
VALUES ?mainAndDependentResourceValueObject { <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> }
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResourceValueObject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#ListValue> .
}
GRAPH <http://www.ontotext.com/explicit> {
?mainAndDependentResourceValueObject <http://www.knora.org/ontology/knora-base#valueHasListNode> ?listNode .
}
GRAPH <http://www.ontotext.com/explicit> {
?listNode <http://www.w3.org/2000/01/rdf-schema#label> ?listNodeLabel .
}
}
} This is the main query result: @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sesame: <http://www.openrdf.org/schema/sesame#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix fn: <http://www.w3.org/2005/xpath-functions#> .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.knora.org/ontology/knora-base#isMainResource> "true"^^xsd:boolean ;
a <http://www.knora.org/ontology/knora-base#Resource> , <http://www.knora.org/ontology/0001/anything#Thing> ;
rdfs:label "testding" ;
<http://www.knora.org/ontology/knora-base#isDeleted> "false"^^xsd:boolean ;
<http://www.knora.org/ontology/knora-base#creationDate> "2018-05-28T15:52:03.897Z"^^xsd:dateTimeStamp ;
<http://www.knora.org/ontology/knora-base#hasPermissions> "CR knora-base:Creator|M knora-base:ProjectMember|V knora-base:KnownUser|RV knora-base:UnknownUser" ;
<http://www.knora.org/ontology/knora-base#attachedToProject> <http://rdfh.ch/projects/0001> ;
<http://www.knora.org/ontology/knora-base#attachedToUser> <http://rdfh.ch/users/BhkfBc3hTeS_IDo-JgXRbQ> ;
<http://www.knora.org/ontology/0001/anything#hasListItem> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/XAhEeE3kSVqM4JPGdLt4Ew> ;
<http://www.knora.org/ontology/0001/anything#hasOtherListItem> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/j8VQjbD0RsyxpyuvfFJCDA> ;
<http://www.knora.org/ontology/0001/anything#hasOtherThing> <http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ> ;
<http://www.knora.org/ontology/0001/anything#hasOtherThingValue> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/uvRVxzL1RD-t9VIQ1TpfUw> ;
<http://www.knora.org/ontology/0001/anything#hasText> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> ;
<http://www.knora.org/ontology/0001/anything#hasRichtext> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/rvB4eQ5MTF-Qxq0YgkwaDg> ;
<http://www.knora.org/ontology/0001/anything#hasDate> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/-rG4F5FTTu2iB5mTBPVn5Q> ;
<http://www.knora.org/ontology/0001/anything#hasInteger> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> ;
<http://www.knora.org/ontology/0001/anything#hasDecimal> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/bXMwnrHvQH2DMjOFrGmNzg> ;
<http://www.knora.org/ontology/0001/anything#hasBoolean> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/IN4R19yYR0ygi3K2VEHpUQ> ;
<http://www.knora.org/ontology/0001/anything#hasUri> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/uBAmWuRhR-eo1u1eP7qqNg> ;
<http://www.knora.org/ontology/0001/anything#hasInterval> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/RbDKPKHWTC-0lkRKae-E6A> ;
<http://www.knora.org/ontology/0001/anything#hasColor> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/TAziKNP8QxuyhC4Qf9-b6w> ;
<http://www.knora.org/ontology/knora-base#hasValue> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/dJ1ES8QTQNepFKF5-EAqdg> a <http://www.knora.org/ontology/knora-base#IntValue> ;
<http://www.knora.org/ontology/knora-base#isDeleted> "false"^^xsd:boolean ;
<http://www.knora.org/ontology/knora-base#valueCreationDate> "2018-05-28T15:52:03.897Z"^^xsd:dateTimeStamp ;
<http://www.knora.org/ontology/knora-base#valueHasInteger> "1"^^xsd:integer ;
<http://www.knora.org/ontology/knora-base#valueHasOrder> "0"^^xsd:integer ;
<http://www.knora.org/ontology/knora-base#valueHasString> "1" ;
<http://www.knora.org/ontology/knora-base#hasPermissions> "CR knora-base:Creator|M knora-base:ProjectMember|V knora-base:KnownUser|RV knora-base:UnknownUser" ;
<http://www.knora.org/ontology/knora-base#attachedToUser> <http://rdfh.ch/users/BhkfBc3hTeS_IDo-JgXRbQ> .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw> <http://www.knora.org/ontology/knora-base#hasValue> <http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> .
<http://rdfh.ch/0001/H6gBWUuJSuuO-CilHV8kQw/values/SZyeLLmOTcCCuS3B0VksHQ> a <http://www.knora.org/ontology/knora-base#TextValue> ;
<http://www.knora.org/ontology/knora-base#isDeleted> "false"^^xsd:boolean ;
<http://www.knora.org/ontology/knora-base#valueCreationDate> "2018-05-28T15:52:03.897Z"^^xsd:dateTimeStamp ;
<http://www.knora.org/ontology/knora-base#valueHasOrder> "0"^^xsd:integer ;
<http://www.knora.org/ontology/knora-base#valueHasString> "test" ;
<http://www.knora.org/ontology/knora-base#hasPermissions> "CR knora-base:Creator|M knora-base:ProjectMember|V knora-base:KnownUser|RV knora-base:UnknownUser" ;
<http://www.knora.org/ontology/knora-base#attachedToUser> <http://rdfh.ch/users/BhkfBc3hTeS_IDo-JgXRbQ> . I think all that is correct. But the responder returns |
@benjamingeer Maybe there is something going wrong when it checks for the presence of all queried dependent resources and values after permission checking. // for each main resource check if all dependent resources and value objects are still present after permission checking
// this ensures that the user has sufficient permissions on the whole query path
queryResWithFullQueryPath: Map[IRI, ConstructResponseUtilV2.ResourceWithValueRdfData] = queryResultsSep.foldLeft(Map.empty[IRI, ConstructResponseUtilV2.ResourceWithValueRdfData]) {
case (acc: Map[IRI, ConstructResponseUtilV2.ResourceWithValueRdfData], (mainResIri: IRI, values: ConstructResponseUtilV2.ResourceWithValueRdfData)) =>
// check for presence of dependent resources: dependentResourceIrisPerMainResource, allResourceIrisFromTypeInspection
val expectedDependentResources: Set[IRI] = dependentResourceIrisPerMainResource(mainResIri) ++ allResourceIrisFromTypeInspection
// check for presence of value objects: valueObjectIrisPerMainResource
val expectedValueObjects: Set[IRI] = valueObjectIrisPerMainResource(mainResIri).values.flatten.toSet
// value property assertions for the current main resource
val valuePropAssertions: Map[IRI, Seq[ConstructResponseUtilV2.ValueRdfData]] = values.valuePropertyAssertions
// all the Iris of dependent resources and value objects contained in `valuePropAssertions`
val resAndValueObjIris: ResourceIrisAndValueObjectIris = traverseValuePropertyAssertions(valuePropAssertions)
// check if the client has sufficient permissions on all dependent resources present in the query path
val allDependentResources: Boolean = resAndValueObjIris.resourceIris.intersect(expectedDependentResources) == expectedDependentResources
// check if the client has sufficient permissions on all value objects Iris present in the query path
val allValueObjects: Boolean = resAndValueObjIris.valueObjectIris.intersect(expectedValueObjects) == expectedValueObjects
if (allDependentResources && allValueObjects) {
// sufficient permissions, include the main resource and its values
acc + (mainResIri -> values)
} else {
// insufficient permissions, skip the resource
acc
}
} I will have a look at it on Monday. |
@benjamingeer Ok, this is the problem: if (allDependentResources && allValueObjects) {
// sufficient permissions, include the main resource and its values
acc + (mainResIri -> values)
} else {
// insufficient permissions, skip the resource
acc
}
I think this line is the problem: val expectedDependentResources: Set[IRI] = dependentResourceIrisPerMainResource(mainResIri) ++ allResourceIrisFromTypeInspection It adds the IRI of the main resource to the collection of dependent resources. Just make sure it gets removed from that collection. |
val expectedDependentResources: Set[IRI] = dependentResourceIrisPerMainResource(mainResIri) ++ allResourceIrisFromTypeInspection Before, the main resource's Iri could not possibly have been contained in that collection because its IRI was not know (the main resource was represented by a variable only). |
Now that I am thinking about it: adding |
…th IRI for main resource.
…sence of dependent resources.
… and restrict it with a filter
@benjamingeer I will add some more tests. I will get back to you in the early afternoon. |
@tobiasschweizer I'm trying another approach: allow I have a test that doesn't work: the last test in |
this works:
result:
|
this also works:
|
Now I understand. It's OK if we get one row of prequery results containing values for multiple dependent resources, because the main query doesn't actually need to know which value goes with which resource. So I think in my example, the prequery should look like this. I removed the values of dependent resources from SELECT DISTINCT ?book (GROUP_CONCAT(DISTINCT(?page); SEPARATOR='') AS ?pageConcat) (GROUP_CONCAT(DISTINCT(?seqnum); SEPARATOR='') AS ?seqnumConcat) (GROUP_CONCAT(DISTINCT(?title); SEPARATOR='') AS ?titleConcat) (GROUP_CONCAT(DISTINCT(?book__LinkValue); SEPARATOR='') AS ?book__LinkValueConcat)
WHERE {
BIND(<http://rdfh.ch/b6b5ff1eb703> AS ?book)
?book <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?book <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
?book <http://www.knora.org/ontology/0803/incunabula#title> ?title .
GRAPH <http://www.ontotext.com/explicit> {
?title <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
?page <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?page <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
?page <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/0803/incunabula#page> .
?page <http://www.knora.org/ontology/knora-base#isPartOf> ?book .
?page <http://www.knora.org/ontology/knora-base#isPartOfValue> ?book__LinkValue .
GRAPH <http://www.ontotext.com/explicit> {
?book__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#LinkValue> .
}
GRAPH <http://www.ontotext.com/explicit> {
?book__LinkValue <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
GRAPH <http://www.ontotext.com/explicit> {
?book__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> ?page .
}
GRAPH <http://www.ontotext.com/explicit> {
?book__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> ?book .
}
?page <http://www.knora.org/ontology/0803/incunabula#seqnum> ?seqnum .
GRAPH <http://www.ontotext.com/explicit> {
?seqnum <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
GRAPH <http://www.ontotext.com/explicit> {
?seqnum <http://www.knora.org/ontology/knora-base#valueHasInteger> ?seqnum__valueHasInteger .
}
FILTER((?seqnum__valueHasInteger <= "10"^^<http://www.w3.org/2001/XMLSchema#integer>))
}
GROUP BY ?book
ORDER BY ASC(?book)
OFFSET 0
LIMIT 25 This prequery returns one row containing everything. So I think that when we generate the prequery, we have to exclude variables from |
Ah now I see, the whole |
I think I had to add values to |
… ORDER BY, ensure subject is main resource.
val incomingLinks = incomingLinksForResource(resourceIri).filterNot {
case (incomingResIri: IRI, assertions: ResourceWithValueRdfData) =>
alreadyTraversed(incomingResIri) || flatResourcesWithValues(incomingResIri).isMainResource
}.flatMap {
case (incomingResIri: IRI, assertions: ResourceWithValueRdfData) =>
assertions.valuePropertyAssertions
} I think this |
@benjamingeer How is that? {
"@id" : "http://rdfh.ch/b6b5ff1eb703",
"@type" : "incunabula:book",
"incunabula:title" : [ {
"@id" : "http://rdfh.ch/b6b5ff1eb703/values/e6d1cf0dcf0e",
"@type" : "knora-api:TextValue",
"knora-api:valueAsString" : "[Das] Narrenschiff (lat.)"
}, {
"@id" : "http://rdfh.ch/b6b5ff1eb703/values/a9fb2247cf0e",
"@type" : "knora-api:TextValue",
"knora-api:valueAsString" : "Stultifera navis (...)"
} ],
"knora-api:hasIncomingLink" : [ {
"@id" : "http://rdfh.ch/54d8597eb803/values/0b6bdaa2-7444-44ec-9c80-cc04c020742a",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/54d8597eb803",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/54d8597eb803/values/0b6bdaa2-7444-44ec-9c80-cc04c020742a",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/54d8597eb803/values/be90332ddf0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 6
},
"rdfs:label" : "a2v"
}
}, {
"@id" : "http://rdfh.ch/68ef9568b903/values/58713048-3e67-4951-806d-fbfcc8ccb79b",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/68ef9568b903",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/68ef9568b903/values/58713048-3e67-4951-806d-fbfcc8ccb79b",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/68ef9568b903/values/ee2c66c2e20e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 10
},
"rdfs:label" : "a4v"
}
}, {
"@id" : "http://rdfh.ch/05c7acceb703/values/ad6b1ac8-7727-4893-9a30-4de4666b4780",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/05c7acceb703",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/05c7acceb703/values/ad6b1ac8-7727-4893-9a30-4de4666b4780",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/05c7acceb703/values/9a9b4d7ddc0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 3
},
"rdfs:label" : "a1r; Titelblatt, recto"
}
}, {
"@id" : "http://rdfh.ch/8fd2ca43b803/values/38ac4bc2-a6d1-4d27-b22e-e793bfcdf9ff",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/8fd2ca43b803",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/8fd2ca43b803/values/38ac4bc2-a6d1-4d27-b22e-e793bfcdf9ff",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/8fd2ca43b803/values/b2e9e647de0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 5
},
"rdfs:label" : "a2r"
}
}, {
"@id" : "http://rdfh.ch/40c11d94b703/values/3ee2ce17-6b6e-4a9c-b747-91d31375ab8e",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/40c11d94b703",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/40c11d94b703/values/3ee2ce17-6b6e-4a9c-b747-91d31375ab8e",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/40c11d94b703/values/8ef40098db0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 2
},
"rdfs:label" : "Vorsatzblatt, verso"
}
}, {
"@id" : "http://rdfh.ch/dee377f3b803/values/2a19b42d-df5b-4289-a455-46094a438dc0",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/dee377f3b803",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/dee377f3b803/values/2a19b42d-df5b-4289-a455-46094a438dc0",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/dee377f3b803/values/d6deccf7e00e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 8
},
"rdfs:label" : "a3v"
}
}, {
"@id" : "http://rdfh.ch/cacc3b09b803/values/b3e7e7c5-b5ac-4efc-9279-067f8ec61a2b",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/cacc3b09b803",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/cacc3b09b803/values/b3e7e7c5-b5ac-4efc-9279-067f8ec61a2b",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/cacc3b09b803/values/a6429a62dd0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 4
},
"rdfs:label" : "a1v; Titelblatt, verso"
}
}, {
"@id" : "http://rdfh.ch/a3e9062eb903/values/a3446ea8-918e-488f-977a-fc8b8de9b003",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/a3e9062eb903",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/a3e9062eb903/values/a3446ea8-918e-488f-977a-fc8b8de9b003",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/a3e9062eb903/values/e28519dde10e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 9
},
"rdfs:label" : "a4r"
}
}, {
"@id" : "http://rdfh.ch/19dee8b8b803/values/f27b06da-6576-445d-b771-22664a397913",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/19dee8b8b803",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/19dee8b8b803/values/f27b06da-6576-445d-b771-22664a397913",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/19dee8b8b803/values/ca378012e00e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 7
},
"rdfs:label" : "a3r"
}
}, {
"@id" : "http://rdfh.ch/7bbb8e59b703/values/448b77cc-b489-40af-83a5-7373d76b4443",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasSource" : {
"@id" : "http://rdfh.ch/7bbb8e59b703",
"@type" : "incunabula:page",
"incunabula:partOfValue" : {
"@id" : "http://rdfh.ch/7bbb8e59b703/values/448b77cc-b489-40af-83a5-7373d76b4443",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTargetIri" : {
"@id" : "http://rdfh.ch/b6b5ff1eb703"
}
},
"incunabula:seqnum" : {
"@id" : "http://rdfh.ch/7bbb8e59b703/values/824db4b2da0e",
"@type" : "knora-api:IntValue",
"knora-api:intValueAsInt" : 1
},
"rdfs:label" : "Vorsatzblatt, recto"
}
} ],
"rdfs:label" : "[Das] Narrenschiff (lat.)",
"@context" : {
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
"knora-api" : "http://api.knora.org/ontology/knora-api/v2#",
"incunabula" : "http://0.0.0.0:3333/ontology/0803/incunabula/v2#"
}
} |
@tobiasschweizer Looks great! |
} | ||
|
||
if (incomingLinks.nonEmpty) { | ||
// link value assertions that point to this resource | ||
val incomingLinkAssertions: Map[IRI, Seq[ValueRdfData]] = referringResources.values.foldLeft(Map.empty[IRI, Seq[ValueRdfData]]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benjamingeer This collects different instances of the same property rather than just overwriting them.
| | ||
| ?title a xsd:string . | ||
| | ||
| FILTER(?title = "Zeitglöcklein des Lebens und Leidens Christi") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so beautiful, it even has Zeitglöcklein in it. 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gravsearch is just a fake, it will always return Zeitglöcklein. So this is the only possible test case.
@benjamingeer Consider the following query: PREFIX beol: <http://0.0.0.0:3333/ontology/0801/beol/simple/v2#>
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/simple/v2#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
CONSTRUCT {
?letter knora-api:isMainResource true .
?letter beol:creationDate ?date .
?letter ?linkingProp1 ?person1 .
?person1 beol:hasFamilyName ?name .
} WHERE {
?letter a knora-api:Resource .
?letter a beol:letter .
?letter beol:creationDate ?date .
beol:creationDate knora-api:objectType knora-api:Date .
?date a knora-api:Date .
?letter ?linkingProp1 ?person1 .
?person1 a knora-api:Resource .
?linkingProp1 knora-api:objectType knora-api:Resource .
FILTER(?linkingProp1 = beol:hasAuthor || ?linkingProp1 = beol:hasRecipient )
OPTIONAL {
?person1 beol:hasFamilyName ?name .
beol:hasFamilyName knora-api:objectType xsd:string .
?name a xsd:string .
FILTER(?name = "Meier")
}
} ORDER BY ?date The prequery looks like follows: SELECT DISTINCT ?letter (GROUP_CONCAT(DISTINCT(?person1); SEPARATOR='') AS ?person1Concat) (GROUP_CONCAT(DISTINCT(?date); SEPARATOR='') AS ?dateConcat) (GROUP_CONCAT(DISTINCT(?name); SEPARATOR='') AS ?nameConcat) (GROUP_CONCAT(DISTINCT(?person1__LinkValue); SEPARATOR='') AS ?person1__LinkValueConcat)
WHERE {
?letter <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?letter <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
?letter <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/0801/beol#letter> .
?letter <http://www.knora.org/ontology/0801/beol#creationDate> ?date .
GRAPH <http://www.ontotext.com/explicit> {
?date <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
?letter ?linkingProp1 ?person1 .
?letter ?linkingProp1__hasLinkToValue ?person1__LinkValue .
GRAPH <http://www.ontotext.com/explicit> {
?person1__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#LinkValue> .
}
GRAPH <http://www.ontotext.com/explicit> {
?person1__LinkValue <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
GRAPH <http://www.ontotext.com/explicit> {
?person1__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> ?letter .
}
GRAPH <http://www.ontotext.com/explicit> {
?person1__LinkValue <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> ?person1 .
}
?person1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.knora.org/ontology/knora-base#Resource> .
GRAPH <http://www.ontotext.com/explicit> {
?person1 <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
OPTIONAL {
?person1 <http://www.knora.org/ontology/0801/beol#hasFamilyName> ?name .
GRAPH <http://www.ontotext.com/explicit> {
?name <http://www.knora.org/ontology/knora-base#isDeleted> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> .
}
}
FILTER((((?linkingProp1 = <http://www.knora.org/ontology/0801/beol#hasAuthor>) && (?linkingProp1__hasLinkToValue = <http://www.knora.org/ontology/0801/beol#hasAuthorValue>)) || ((?linkingProp1 = <http://www.knora.org/ontology/0801/beol#hasRecipient>) && (?linkingProp1__hasLinkToValue = <http://www.knora.org/ontology/0801/beol#hasRecipientValue>))))
GRAPH <http://www.ontotext.com/explicit> {
?date <http://www.knora.org/ontology/knora-base#valueHasStartJDN> ?date__valueHasStartJDN .
}
}
GROUP BY ?letter ?date__valueHasStartJDN
ORDER BY ASC(?date__valueHasStartJDN) ASC(?letter)
OFFSET 0
LIMIT 25
The filter inside the The result is this: {
"@id" : "http://rdfh.ch/0801/_B3lQa6tSymIq7_7SowBsA",
"@type" : "beol:letter",
"beol:creationDate" : {
"@id" : "http://rdfh.ch/0801/_B3lQa6tSymIq7_7SowBsA/values/L2gv0paYSymiENk1c0fAAQ",
"@type" : "knora-api:DateValue",
"knora-api:dateValueHasCalendar" : "GREGORIAN",
"knora-api:dateValueHasEndDay" : 4,
"knora-api:dateValueHasEndEra" : "CE",
"knora-api:dateValueHasEndMonth" : 6,
"knora-api:dateValueHasEndYear" : 2018,
"knora-api:dateValueHasStartDay" : 4,
"knora-api:dateValueHasStartEra" : "CE",
"knora-api:dateValueHasStartMonth" : 6,
"knora-api:dateValueHasStartYear" : 2018,
"knora-api:valueAsString" : "GREGORIAN:2018-06-04 CE"
},
"beol:hasAuthorValue" : {
"@id" : "http://rdfh.ch/0801/_B3lQa6tSymIq7_7SowBsA/values/Cvp07eTqQQSnYdcvqlWW_g",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTarget" : {
"@id" : "http://rdfh.ch/0801/VvYVIy-FSbOJBsh2d9ZFJw",
"@type" : "beol:person",
"beol:hasFamilyName" : {
"@id" : "http://rdfh.ch/0801/VvYVIy-FSbOJBsh2d9ZFJw/values/5K24YxlwQ9OXcYjB0jRR4Q",
"@type" : "knora-api:TextValue",
"knora-api:valueAsString" : "Meier"
},
"rdfs:label" : "Testperson2"
}
},
"beol:hasRecipientValue" : {
"@id" : "http://rdfh.ch/0801/_B3lQa6tSymIq7_7SowBsA/values/DVqPKuBBSIauVqjUC7bNvA",
"@type" : "knora-api:LinkValue",
"knora-api:linkValueHasTarget" : {
"@id" : "http://rdfh.ch/0801/H7s3FmuWTkaCXa54eFANOA",
"@type" : "beol:person",
"beol:hasFamilyName" : {
"@id" : "http://rdfh.ch/0801/H7s3FmuWTkaCXa54eFANOA/values/7LhL_JdpTA-E0oQ1hdtPDQ",
"@type" : "knora-api:TextValue",
"knora-api:valueAsString" : "Muster"
},
"rdfs:label" : "Testperson1"
}
},
"rdfs:label" : "Testbrief1",
"@context" : {
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
"knora-api" : "http://api.knora.org/ontology/knora-api/v2#",
"beol" : "http://0.0.0.0:3333/ontology/0801/beol/v2#"
}
} I would expect that the name is only returned if it is "Meier". But therefore we need the filter. |
Looks like a bug. :) |
I think so. Maybe |
@benjamingeer I tried the query from #870 (comment) and it worked. We should add it as a test. Thanks for fixing this! |
I've already added it in |
@benjamingeer I also added it as an e2e tests. Doppelt genäht hält besser. |
@tobiasschweizer Can I merge this now? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thx!
lang
function to be used in a comparison inside AND/OR (Gravsearch AND expression failing #846).lang
to be used with!=
.match
function to be the top-level expression in aFILTER
.BIND
).For a subsequent PR:
Fixes #846.
Resolves #650.
Fixes #878.
Fixes #879.
Resolves #871.