Skip to content

Commit

Permalink
fix: allow ordering by label in Gravsearch (DEV-2546) (#2798)
Browse files Browse the repository at this point in the history
  • Loading branch information
BalduinLandolt committed Aug 21, 2023
1 parent 246f1da commit ca4553e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
Expand Up @@ -309,6 +309,33 @@ class SearchResponderV2Spec extends CoreSpec with ImplicitSender {
}
}

"perform an extended search ordered by label" in {

val queryAsc = searchResponderV2SpecFullData.constructQuerySortByLabel

appActor ! GravsearchRequestV2(
constructQuery = queryAsc,
targetSchema = ApiV2Complex,
schemaOptions = SchemaOptions.ForStandoffWithTextValues,
requestingUser = SharedTestDataADM.anonymousUser
)

val asc = expectMsgPF(timeout) { case response: ReadResourcesSequenceV2 => response }
assert(asc.resources.head.label == "A blue thing")

val queryDesc = searchResponderV2SpecFullData.constructQuerySortByLabelDesc

appActor ! GravsearchRequestV2(
constructQuery = queryDesc,
targetSchema = ApiV2Complex,
schemaOptions = SchemaOptions.ForStandoffWithTextValues,
requestingUser = SharedTestDataADM.anonymousUser
)

val desc = expectMsgPF(timeout) { case response: ReadResourcesSequenceV2 => response }
assert(desc.resources.head.label == "visible thing with hidden int values")
}

}

}
Expand Up @@ -417,4 +417,46 @@ class SearchResponderV2SpecFullData(implicit stringFormatter: StringFormatter) {
querySchema = Some(ApiV2Simple)
)

val constructQuerySortByLabel: ConstructQuery = ConstructQuery(
constructClause = ConstructClause(
Vector(
StatementPattern(
QueryVariable("r"),
IriRef("http://api.knora.org/ontology/knora-api/simple/v2#isMainResource".toSmartIri, None),
XsdLiteral("true", "http://www.w3.org/2001/XMLSchema#boolean".toSmartIri)
)
),
querySchema = Some(ApiV2Simple)
),
whereClause = WhereClause(
Vector(
StatementPattern(
QueryVariable("r"),
IriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type".toSmartIri, None),
IriRef("http://0.0.0.0:3333/ontology/0001/anything/simple/v2#Thing".toSmartIri, None)
),
StatementPattern(
QueryVariable("r"),
IriRef("http://www.w3.org/2000/01/rdf-schema#label".toSmartIri, None),
QueryVariable("l")
)
),
Set(
QueryVariable("r"),
QueryVariable("l"),
IriRef("http://api.knora.org/ontology/knora-api/simple/v2#isMainResource".toSmartIri, None),
IriRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type".toSmartIri, None),
IriRef("http://0.0.0.0:3333/ontology/0001/anything/simple/v2#Thing".toSmartIri, None),
IriRef("http://www.w3.org/2000/01/rdf-schema#label".toSmartIri, None)
),
querySchema = Some(ApiV2Simple)
),
orderBy = Vector(OrderCriterion(QueryVariable("l"), true)),
querySchema = Some(ApiV2Simple)
)

val constructQuerySortByLabelDesc: ConstructQuery = constructQuerySortByLabel.copy(
orderBy = Vector(OrderCriterion(QueryVariable("l"), false))
)

}
Expand Up @@ -107,6 +107,9 @@ abstract class AbstractPrequeryGenerator(
private var valueVariablesAutomaticallyGenerated: List[Map[QueryVariable, Set[GeneratedQueryVariable]]] =
List(Map.empty[QueryVariable, Set[GeneratedQueryVariable]])

// Variables that point to actual literals; the only case currently would be rdfs:label
private var literalVariables: Set[QueryVariable] = Set.empty

// Variables mentioned in the UNION block that is currently being processed, so we can ensure that a variable
// is bound before it is used in a FILTER. This is a stack of sets, with one element per level of union blocks.
private var variablesInUnionBlocks: List[Set[QueryVariable]] = List.empty
Expand Down Expand Up @@ -252,7 +255,7 @@ abstract class AbstractPrequeryGenerator(

generatedVarsForOrderBy.headOption

case None => None
case None => if (literalVariables.contains(valueVar)) Some(valueVar) else None
}

// Generated statements for date literals, so we don't generate the same statements twice.
Expand Down Expand Up @@ -676,6 +679,13 @@ abstract class AbstractPrequeryGenerator(
}
}

private def recordLiteralVariables(statementPattern: StatementPattern): Unit =
statementPattern match {
case StatementPattern(_, IriRef(pred, None), obj: QueryVariable) if pred.toIri == OntologyConstants.Rdfs.Label =>
literalVariables += obj
case _ => ()
}

protected def processStatementPatternFromWhereClause(
statementPattern: StatementPattern,
inputOrderBy: Seq[OrderCriterion],
Expand Down Expand Up @@ -719,6 +729,8 @@ abstract class AbstractPrequeryGenerator(
// so we can make sure that they're defined before they're used in a FILTER pattern.
recordVariablesInUnionBlock(statementPattern)

recordLiteralVariables(statementPattern)

additionalStatementsForSubj ++ additionalStatementsForWholeStatement ++ additionalStatementsForObj
}
)
Expand Down
Expand Up @@ -460,7 +460,7 @@ final case class SearchResponderV2Live(

// Create a Select prequery
querySchema <-
ZIO.fromOption(inputQuery.querySchema).orElseFail(AssertionException(s"WhereClause has no querySchema"))
ZIO.fromOption(inputQuery.querySchema).orElseFail(AssertionException(s"InputQuery has no querySchema"))
gravsearchToPrequeryTransformer: GravsearchToPrequeryTransformer =
new GravsearchToPrequeryTransformer(
constructClause = inputQuery.constructClause,
Expand Down

0 comments on commit ca4553e

Please sign in to comment.