Skip to content
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 result sorted on linked resource's property #1575

Open
gfoo opened this issue Jan 14, 2020 · 18 comments
Open

Gravsearch result sorted on linked resource's property #1575

gfoo opened this issue Jan 14, 2020 · 18 comments

Comments

@gfoo
Copy link

gfoo commented Jan 14, 2020

I try to sort the result of a gravsearch query according to a linked resource's property. In my following example, I'm searching for DraftPersons, but I want to sort the result on linked resource Person hasName property and I get this error:

{
    "knora-api:error": "org.knora.webapi.GravsearchException: Variable ?hasName is used in ORDER BY, but does not represent a value of the main resource",
    "@context": {
        "knora-api": "http://api.knora.org/ontology/knora-api/v2#"
    }
}

Is that a bug?

PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
PREFIX knora-simple-api: <http://api.knora.org/ontology/knora-api/simple/v2#>
PREFIX ll: <http://0.0.0.0:3333/ontology/0113/lumieres-lausanne/v2#>

CONSTRUCT {
  ?DraftPerson knora-api:isMainResource true .
  ?DraftPerson ll:isDraftOf ?isDraftOf .
  ?isDraftOf ll:hasName ?hasName .
  
} WHERE {
  
  ?DraftPerson a ll:DraftPerson .
  ?DraftPerson ll:isDraftOf ?isDraftOf .
  ?isDraftOf a ll:Person .
  ?isDraftOf ll:hasName ?hasName .

 {
  ?DraftPerson ll:hasPlaceBirth ?hasPlaceBirth .
  ?hasPlaceBirth knora-api:valueAsString ?hasPlaceBirth_Value .
  FILTER knora-api:match(?hasPlaceBirth_Value, "*Laus*")
 }
 UNION
 {
  ?DraftPerson ll:hasPlaceDeath ?hasPlaceDeath .
  ?hasPlaceDeath knora-api:valueAsString ?hasPlaceDeath_Value .
  FILTER knora-api:match(?hasPlaceDeath_Value, "*Laus*")
 }

}
ORDER BY ASC(?hasName)

(As workaround, I think I can reverse the query to have Person as main resource)

@tobiasschweizer
Copy link
Contributor

Variable ?hasName is used in ORDER BY, but does not represent a value of the main resource

In your query, ?hasName is not a value of the main resource which causes the exception. I have never thought of sorting the main resource by a dependent resource's property.

@tobiasschweizer
Copy link
Contributor

Also what if there are several dependent resources with several values?

@gfoo
Copy link
Author

gfoo commented Jan 15, 2020

Also what if there are several dependent resources with several values?

Not sure to understand !

But firstly is that possible in Sparql what I'm asking for? if it is not possible the question is closed!

@gfoo
Copy link
Author

gfoo commented Jan 15, 2020

I have other cases where reverse the query starts to be very annoying and may be not performant because of space search. In the following example, I'm searching a BibliographicNotice and to reverse the query I should start by Person (to sort on hasName), go to a Contribution and then go to BibliographicNotice to apply all my FILTER...

PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
PREFIX knora-simple-api: <http://api.knora.org/ontology/knora-api/simple/v2#>
PREFIX ll: <http://0.0.0.0:3333/ontology/0113/lumieres-lausanne/v2#>

CONSTRUCT {
  ?BibliographicNotice knora-api:isMainResource true .
  ?BibliographicNotice ll:hasContribution ?hasContribution .
?hasContribution ll:isContributor ?isContributor .
?isContributor ll:hasName ?hasName .
  
} WHERE {
  
  ?BibliographicNotice a ll:BibliographicNotice .
  
  ?BibliographicNotice ll:hasContribution ?hasContribution .
?hasContribution a ll:Contribution .

?hasContribution ll:isContributor ?isContributor .
?isContributor a ll:Person .

?isContributor ll:hasName ?hasName .


  
{

{
?BibliographicNotice ll:bibliographicNoticeHasTitle ?bibliographicNoticeHasTitle .

?bibliographicNoticeHasTitle knora-api:valueAsString ?bibliographicNoticeHasTitle_Value .
    FILTER knora-api:match(?bibliographicNoticeHasTitle_Value, "*")
}
UNION
{

[... many other union there on BibliographicNotice resources]

}
ORDER BY ASC(?hasName)

@gfoo
Copy link
Author

gfoo commented Jan 16, 2020

Also what if there are several dependent resources with several values?

ok, got it, I didn't think that you have to group by on main resource... so we could maybe use an order by on the aggregated result of hasName?

Test data: test_data.trig.zip

And how I could order by the aggregated values of hasName (in my particular case I have a way to select the first author to only get one hasName)

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX td: <http://test_data#>
SELECT 
?biblio 
(GROUP_CONCAT(?firstHasName) AS ?Agg_firstHasName) 
WHERE { 
	?biblio rdf:type td:Biblio .
    ?biblio td:hasContrib ?hasContrib .
    ?hasContrib td:hasSeqNum ?hasSeqNum .
    FILTER(?hasSeqNum = 1) .
    ?hasContrib td:hasAuthor ?firstHasAuthor .
    ?firstHasAuthor td:hasName ?firstHasName .
} GROUP BY ?biblio 
ORDER BY ASC(?Agg_firstHasName)

@mrivoal
Copy link

mrivoal commented Jan 16, 2020

@tobiasschweizer, @benjamingeer

It would be really good to have your feedbacks on this if you can spare some time. We are in a dead end and don't know how we could deliver this feature requested by Lumieres.Lausanne.

Do you think Gravsearch wouldn't be able to perform this query any time soon and we should look for a workaround ? No idea which one yet...

@benjamingeer
Copy link

This limitation is part of the current design of Gravsearch.

In any case, it only makes sense to order by single values, not by multiple values. Is there a 1:1 relationship between a DraftPerson and a Person?

And how I could order by the aggregated values of hasName

With GROUP_CONCAT, "The order of the strings is not specified", so it wouldn't be useful for sorting:

https://stackoverflow.com/a/47460929

Anyway, GROUP BY can only be used a SELECT query, and Gravsearch doesn't support SELECT queries.

I think it would be worth thinking about adding support for SELECT in Gravsearch, which could also be a way to solve your other issue here.

But this would take some time to develop.

Since DraftPerson has the property ll:hasPlaceBirth, couldn't it also have the property ll:hasName? Would that solve your problem?

@mrivoal
Copy link

mrivoal commented Jan 17, 2020

The modeling is not the issue, we have 2 other cases with doesn't involve this peculiar example. Here is another one: a Transcription to which point a full BibliographicReference with a hasWritingDate, the BibliographicReference itself is also linked to an Author.

And we would like to be able to display Transcription according first to the property hasName of the Author and, if there are several instances of a Transcription for the same Author, we would like to sort the Transcription by the hasWritingDate property of the BibliographicReference.

@benjamingeer
Copy link

My suggestion was just a workaround, because as I said, if we do implement something like this, it will take time, and it sounds like you need a solution quickly.

And you haven't answered my question: could there be multiple sort keys for each item that needs to be sorted? Could there be more than one Author per Transcription? Could there be more than one Date per BibliographicReference? If so, sorting becomes very difficult.

@mrivoal
Copy link

mrivoal commented Jan 17, 2020

Well I only wanted to make a partial answer and leave the rest to @gfoo.

There is only one Date for BibliographicReference. However, there could more than one Author for a BibliographicReference, yes.

And you are right, we need a solution quickly... Or we could go in production without and implement it in the following months, when/if the feature is supported in Gravsearch. But I think it would make sense, right?

@benjamingeer
Copy link

If there can be more than one Author per BibliographicReference (or perhaps, more than one name per Author), how would you decide which name to use as the sort key? The first one alphabetically? The last one? Would you still want to return all the names in the response, even if only one name was used for sorting?

I think that if you need a workaround quickly, it will have to involve a change to your ontology, to ensure that all your sort keys are in the main resource. Longer term, once we understand better what your requirements are, we can see if it's possible to do what you want in SPARQL (and hence in Gravsearch).

@benjamingeer
Copy link

(a change to your ontology, or a change to your Gravsearch queries)

@mrivoal
Copy link

mrivoal commented Jan 17, 2020

Actually, we also have a hasSequenceNumber property for Author which allows to sort several authors in the right order for a correct display of the bibliographic reference.

@mrivoal
Copy link

mrivoal commented Jan 17, 2020

Changing the ontology now is not an option. We would rather not provide the feature at all (but maybe later) than change the ontology now because the ontology and the web application for this project are very complicated and we are to release around mid February.

@benjamingeer
Copy link

Actually, we also have a hasSequenceNumber property for Author which allows to sort several authors in the right order

OK, but I'm not sure it's possible to do that in SPARQL. If it is possible, it could involve some rather complicated SPARQL code, which Gravsearch would have to generate. Implementing that could be a lot of work.

One thing you could do, if you want to help, is figure out how to do this yourself in a SPARQL SELECT query. You could start by writing a Gravsearch query that's close to what you want (without the ORDER BY), and get the resulting generated SELECT prequery by uncommenting this line:

https://github.com/dasch-swiss/knora-api/blob/develop/webapi/src/main/scala/org/knora/webapi/responders/v2/SearchResponderV2.scala#L458

Then see if you can modify the prequery so it does what you want. Then we would have a proof of concept and something to start with.

@gfoo
Copy link
Author

gfoo commented Jan 17, 2020

One thing you could do, if you want to help, is figure out how to do this yourself in a SPARQL SELECT query

this is what I've tried to explain in my comment above #1575 (comment) (with simplified rdf data of course)

With a group by that you generate from a gravsearch query, we can sort on the aggregated column because we assume that there is only one value in the concat.

In all our cases we can select one value, so the concat order is no more a problem.

In the gravsearch query at the beginning of this issue I used ORDER BY ASC(?hasName), but it is not possible of course, we could imagine a ORDER_CONCAT only available to var not from the main resource ?

@benjamingeer
Copy link

@gfoo OK, thanks, now I understand. If there is always a way to select only one value, then I think this becomes much easier to implement (otherwise I think we would need a subquery, which I would really rather avoid because it introduces all sorts of difficulties).

@tobiasschweizer would you be able to look at this with me when I'm in Basel next month?

@tobiasschweizer
Copy link
Contributor

would you be able to look at this with me when I'm in Basel next month?

Yes, sure. But unfortunately I cannot make any promises by when this could be implemented.

@subotic subotic added this to the Backlog milestone Feb 7, 2020
@irinaschubert irinaschubert removed this from the Backlog milestone Dec 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants