Skip to content
Permalink
Browse files
fix(gravsearch): don't move the patterns with resource IRI after topo…
…logical sorting (DSP-1620) (#1856)

* fix(gravsearch): don't move the patterns with resource IRI after topological sorting

* refactor (gravsearch): delete obsolete moveResourceIrisToBeginning method

* fix(gravsearch): increase query time out

* docs (gravsearch): improve docs
  • Loading branch information
SepidehAlassi committed May 12, 2021
1 parent 161ea31 commit 6022c91e442058cc48c58f93da6071f5b00661fc
@@ -267,7 +267,8 @@ main resource, which must be represented by a variable.
It is possible to do a Gravsearch query in which the IRI of the main resource
is already known, e.g. to request specific information about that resource and
perhaps about linked resources. In this case, the IRI of the main resource must
be assigned to a variable using `BIND`.
be assigned to a variable using `BIND`. Note that `BIND` statements slow the query down,
therefore we recommend that you do not use them unless you have to.

Properties can be represented by an IRI or a query variable. If a
property is represented by a query variable, it can be restricted to
@@ -543,7 +543,7 @@ app {
host = ${?KNORA_WEBAPI_TRIPLESTORE_HOST}

// timeout for triplestore queries. can be same or lower then akka.http.server.request-timeout.
query-timeout = 10 seconds
query-timeout = 20 seconds

// timeout for tripelstore updates. can be same or lower then akka.http.server.request-timeout.
update-timeout = 30 minutes
@@ -48,7 +48,7 @@ object SparqlTransformer {
override def transformFilter(filterPattern: FilterPattern): Seq[QueryPattern] = Seq(filterPattern)

override def optimiseQueryPatterns(patterns: Seq[QueryPattern]): Seq[QueryPattern] = {
moveBindToBeginning(moveResourceIrisToBeginning(moveLuceneToBeginning(patterns)))
moveBindToBeginning(moveLuceneToBeginning(patterns))
}

override def transformLuceneQueryPattern(luceneQueryPattern: LuceneQueryPattern): Seq[QueryPattern] = {
@@ -88,7 +88,7 @@ object SparqlTransformer {
override def transformFilter(filterPattern: FilterPattern): Seq[QueryPattern] = Seq(filterPattern)

override def optimiseQueryPatterns(patterns: Seq[QueryPattern]): Seq[QueryPattern] = {
moveBindToBeginning(optimiseIsDeletedWithFilter(moveResourceIrisToBeginning(moveLuceneToBeginning(patterns))))
moveBindToBeginning(optimiseIsDeletedWithFilter(moveLuceneToBeginning(patterns)))
}

override def transformLuceneQueryPattern(luceneQueryPattern: LuceneQueryPattern): Seq[QueryPattern] =
@@ -118,7 +118,7 @@ object SparqlTransformer {
override def transformFilter(filterPattern: FilterPattern): Seq[QueryPattern] = Seq(filterPattern)

override def optimiseQueryPatterns(patterns: Seq[QueryPattern]): Seq[QueryPattern] = {
moveBindToBeginning(moveResourceIrisToBeginning(moveLuceneToBeginning(patterns)))
moveBindToBeginning(moveLuceneToBeginning(patterns))
}

override def transformLuceneQueryPattern(luceneQueryPattern: LuceneQueryPattern): Seq[QueryPattern] =
@@ -145,7 +145,7 @@ object SparqlTransformer {
override def transformFilter(filterPattern: FilterPattern): Seq[QueryPattern] = Seq(filterPattern)

override def optimiseQueryPatterns(patterns: Seq[QueryPattern]): Seq[QueryPattern] = {
moveBindToBeginning(optimiseIsDeletedWithFilter(moveResourceIrisToBeginning(moveLuceneToBeginning(patterns))))
moveBindToBeginning(optimiseIsDeletedWithFilter(moveLuceneToBeginning(patterns)))
}

override def transformLuceneQueryPattern(luceneQueryPattern: LuceneQueryPattern): Seq[QueryPattern] =
@@ -294,45 +294,6 @@ object SparqlTransformer {
luceneQueryPatterns ++ otherPatterns
}

/**
* Optimises a query by moving statement patterns containing resource IRIs to the beginning of a block.
*
* @param patterns the query patterns to be optimised.
* @return the optimised query patterns.
*/
def moveResourceIrisToBeginning(patterns: Seq[QueryPattern]): Seq[QueryPattern] = {
val (patternsWithResourceIris: Seq[QueryPattern], otherPatterns: Seq[QueryPattern]) = patterns.partition {
case statementPattern: StatementPattern =>
val subjIsResourceIri = statementPattern.subj match {
case iriRef: IriRef if iriRef.iri.isKnoraResourceIri => true
case _ => false
}

// Don't move statements whose predicate is rdf:subject or rdf:object: their subject
// is a link value that needs to be defined first.
val statementIsInLinkValue = statementPattern.pred match {
case iriRef: IriRef =>
iriRef.iri.toString match {
case OntologyConstants.Rdf.Subject | OntologyConstants.Rdf.Object => true
case _ => false
}

case _ => false
}

val objIsResourceIri = statementPattern.obj match {
case iriRef: IriRef if iriRef.iri.isKnoraResourceIri => true
case _ => false
}

!statementIsInLinkValue && (subjIsResourceIri || objIsResourceIri)

case _ => false
}

patternsWithResourceIris ++ otherPatterns
}

/**
* Transforms a statement in a WHERE clause for a triplestore that does not provide inference.
*
@@ -184,72 +184,6 @@ class SparqlTransformerSpec extends CoreSpec() {
optimisedPatterns should ===(expectedPatterns)
}

"move a statement with a resource IRI as object to the beginning of a block" in {
val typeStatement = StatementPattern.makeExplicit(
subj = QueryVariable("foo"),
pred = IriRef(OntologyConstants.Rdf.Type.toSmartIri),
obj = IriRef("http://www.knora.org/ontology/0001/anything#Thing".toSmartIri)
)
val hasValueStatement =
StatementPattern.makeExplicit(subj = QueryVariable("foo"),
pred = IriRef("http://www.knora.org/ontology/0001/anything#hasText".toSmartIri),
obj = QueryVariable("text"))
val linkStatement = StatementPattern.makeExplicit(
subj = QueryVariable("foo"),
pred = IriRef("http://www.knora.org/ontology/0001/anything#hasOtherThing".toSmartIri),
obj = IriRef("http://rdfh.ch/0001/a-thing".toSmartIri)
)

val patterns: Seq[StatementPattern] = Seq(
typeStatement,
hasValueStatement,
linkStatement
)

val optimisedPatterns = SparqlTransformer.moveResourceIrisToBeginning(patterns)

val expectedPatterns: Seq[StatementPattern] = Seq(
linkStatement,
typeStatement,
hasValueStatement
)

optimisedPatterns should ===(expectedPatterns)
}

"move a statement with a resource IRI as subject to the beginning of a block" in {
val typeStatement = StatementPattern.makeExplicit(
subj = QueryVariable("foo"),
pred = IriRef(OntologyConstants.Rdf.Type.toSmartIri),
obj = IriRef("http://www.knora.org/ontology/0001/anything#Thing".toSmartIri)
)
val hasValueStatement =
StatementPattern.makeExplicit(subj = QueryVariable("foo"),
pred = IriRef("http://www.knora.org/ontology/0001/anything#hasText".toSmartIri),
obj = QueryVariable("text"))
val linkStatement = StatementPattern.makeExplicit(
subj = IriRef("http://rdfh.ch/0001/a-thing".toSmartIri),
pred = IriRef("http://www.knora.org/ontology/0001/anything#hasOtherThing".toSmartIri),
obj = QueryVariable("foo")
)

val patterns: Seq[StatementPattern] = Seq(
typeStatement,
hasValueStatement,
linkStatement
)

val optimisedPatterns = SparqlTransformer.moveResourceIrisToBeginning(patterns)

val expectedPatterns: Seq[StatementPattern] = Seq(
linkStatement,
typeStatement,
hasValueStatement
)

optimisedPatterns should ===(expectedPatterns)
}

"expand an rdf:type statement to simulate RDFS inference" in {
val typeStatement = StatementPattern.makeInferred(
subj = QueryVariable("foo"),

0 comments on commit 6022c91

Please sign in to comment.