Skip to content

Commit

Permalink
fix(gravsearch): don't move the patterns with resource IRI after topo…
Browse files Browse the repository at this point in the history
…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 6022c91
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 111 deletions.
3 changes: 2 additions & 1 deletion docs/03-apis/api-v2/query-language.md
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion webapi/src/main/resources/application.conf
Expand Up @@ -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
Expand Down
Expand Up @@ -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] = {
Expand Down Expand Up @@ -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] =
Expand Down Expand Up @@ -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] =
Expand All @@ -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] =
Expand Down Expand Up @@ -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.
*
Expand Down
Expand Up @@ -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"),
Expand Down

0 comments on commit 6022c91

Please sign in to comment.