Query over user's POD

Hi,
I am trying to make a query(SPARQL) where given a folder I can list content of all resources in that folder. For example: A query with inbox as an endpoint that shows me the title and summary of all the notifications that are inside that folder.

An example of inbox would be this:

@prefix : <#>.
@prefix inbox: <>.
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix terms: <http://purl.org/dc/terms/>.
@prefix XML: <http://www.w3.org/2001/XMLSchema#>.
@prefix st: <http://www.w3.org/ns/posix/stat#>.
@prefix tur: <http://www.w3.org/ns/iana/media-types/text/turtle#>.

inbox:
    a ldp:BasicContainer, ldp:Container;
    terms:modified "2020-04-01T20:41:34Z"^^XML:dateTime;
    ldp:contains
        <1585184241983.ttl>, <1585190831744.ttl>, <1585437347737.ttl>,
        <1585755866235.ttl>;
    st:mtime 1585773694.755;
    st:size 4096.
<1585184241983.ttl>
    a tur:Resource, ldp:Resource;
    terms:modified "2020-04-01T16:36:56Z"^^XML:dateTime;
    st:mtime 1585759016.9;
    st:size 877.
<1585190831744.ttl>
    a tur:Resource, ldp:Resource;
    terms:modified "2020-04-01T16:43:35Z"^^XML:dateTime;
    st:mtime 1585759415.31;
    st:size 877.
<1585437347737.ttl>
    a tur:Resource, ldp:Resource;
    terms:modified "2020-04-01T16:59:30Z"^^XML:dateTime;
    st:mtime 1585760370.042;
    st:size 877.
<1585755866235.ttl>
    a tur:Resource, ldp:Resource;
    terms:modified "2020-04-01T16:35:53Z"^^XML:dateTime;
    st:mtime 1585758953.69;
    st:size 886.

An example of notification:

@prefix terms: <http://purl.org/dc/terms#>.
        @prefix as: <https://www.w3.org/ns/activitystreams#>.
        @prefix schema: <http://schema.org/>.
        @prefix solid: <https://www.w3.org/ns/solid/terms#>.
        @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
        
        <> a as:Offer;
            schema:license <https://creativecommons.org/licenses/by-sa/4.0/>;
            terms:title "Route share";
            as:summary "Testing";
            as:actor <https://christianpelaez98.solid.community/profile/card#me>;
            as:target <https://pruebaChristian.solid.community/profile/card#me>;
            as:object <https://christianpelaez98.solid.community/ejemplos/ruta1.ttl>;
            solid:read "true"^^xsd:boolean;
            as:published "2020-03-26T00:57:21.984Z"^^xsd:dateTime.

Anybody got an idea? I have searched the forum and issues but I have not found anything that talks about this. Thanks!!:dancer:

Hi Christian, unfortunately Solid does not currently support SPARQL queries on Pods, so youā€™ll have to fetch the contents of all those files individually, Iā€™m afraid.

1 Like

Okay :frowning_face:, thank you!!

I had same kind of question for Shighl lib, Iā€™ve used a log.ttl file where is written this kind summary data. Talk at 16:00 :wink:

Using RDF-easy, hereā€™s how:

let contents = await rdf.query( containerURI, `
      SELECT ?uri ?size WHERE {
          <> ldp:contains ?uri. 
          ?uri stat:size ?size.
      }
`)
for(var c of contents){ 
     let thisNotifcation = c.uri
     // send a second query to c.uri to get data in each notification) 
}
5 Likes

Hi @jeffz ,
I could not find rdf-easy on npm. I tried running ā€œnpm install rdf-easyā€. Am I doing something wrong?
image

Thanks

I stopped development of rdf-easy because there are already so many rdf handlers and I have too many libraries to maintain. But I always did kind of like it. You should be able to clone or download the github repo. Let me know if you end up using it.

Just tried:
import auth2 from ā€˜solid-auth-cliā€™
import RDFEasy from ā€˜ā€¦/lib/rdf-easyā€™;

const rdf = new RDFEasy(auth2)

if (_.isEmpty(exclude)) {
    try {
        file = await rdf.query(cache, `
            SELECT DISTINCT ?s {
                ?s ?p ?o .
            }
        `);
    } catch (e) {
        console.error(e)
    }
}

I get the following error. I also tried with solid-auth-client with no luck.
Error: Fetcher: https://jorge.pod.ideniox.com/outbox/cache.ttl Unauthenticated
at Fetcher.failFetch (fetcher.js:1112)
at fetcher.js:1815
at async RDFeasy._load (rdflib-easy.js:82)
at async RDFeasy._runQuery (rdflib-easy.js:32)
at async RDFeasy.query (rdflib-easy.js:24)
at async getNotifications (things.js:331)
at async Notification.load (notification.js:11)

I understand you may not be in the mood to look onto a issue of a code you are not longer maintaining. Would you kindly be able to recommend any rdf handler?

Cheers.

If you want to, you can probably fix that by changing two lines in rdf-easy.js. Find the two lines that define the fetcher.

// CHANGE THIS IN BOTH PLACES IT OCCURS
this.fetcher = $rdf.fetcher(this.store,{fetch:this._auth.fetch})
// TO THIS
this.fetcher = $rdf.fetcher(this.store,{fetch:this._auth.fetch.bind(this._auth)})

If you try that and it works for you, let me know. See this list of alternative linked data libraries. Query-LDflex and Tripledoc are both very robust and well-maintained.

If you have more questions about rdf-easy, Iā€™m glad to try to answer them. @bourgeoa had talked about reviving and adding to the project so itā€™s not impossible it will continue.

I have tried your suggestion but I got the same error. I am just trying to do select query and update query ttl the same way that solid does it for trusted apps for instance.

Iā€™ll download it and take a look.

Just checking ā€¦ you did perform a login before making the request?

Yes, I have I use.
import {AuthButton, LoggedIn} from ā€œ@solid/reactā€;

using solid-auth-client instead of solid-auth-cli I get
query.js:616 Uncaught TypeError: Cannot read property ā€˜initBindingsā€™ of undefined
at query.js:616

You have to use the same auth library as when you login. Solid-auth-client is for browsers and solid-auth-cli is for nodejs so if youā€™re in a browser, only use solid-auth-client or the newer @inrupt/solid-client-authn-browser.

I use solid-auth-client which is the same I use for log in.
In my example I do:

import auth from ā€œsolid-auth-clientā€;
const $rdf = require(ā€˜rdflibā€™)

const graph = $rdf.graph()
const fetcher = $rdf.fetcher(graph,{fetch: auth.fetch.bind(auth)})
await fetcher.load(cache)
const j = await fetcher.store.query( SELECT DISTINCT ?s { ?s ?p ?o . }
);

And I get a Uncaught TypeError: Cannot read property ā€˜initBindingsā€™ of undefined

Youā€™re missing the SPARQLToQuery step. Try this (use solid-auth-client instead of SolidNodeClient if in browser:

import * as $rdf from 'rdflib';                                                 
import {SolidNodeClient} from 'solid-node-client';                                            
const auth = new SolidNodeClient();                                             
const store = $rdf.graph();                                                     
const fetcher = $rdf.fetcher(store,{fetch:auth.fetch.bind(auth)});              
                                                                                
const ex = "https://example.com/";                                              
store.add( $rdf.sym(ex+'Foo'), $rdf.sym(ex+'has'), 'Bar');                      
store.add( $rdf.sym(ex+'Baz'), $rdf.sym(ex+'has'), 'Bop');                      
let sparql = "SELECT ?s WHERE { ?s ?p 'Bar' . }";                               
let preparedQuery =  $rdf.SPARQLToQuery(sparql,false,store)                     
store.query( preparedQuery, async(results) =>  {                                
  console.log(results['?s'].value); // prints "https://example.com/Foo"         
});                                                                             

Kinda stuck in hereā€¦sorry to pester.
I have a file called test.ttl as below.

<> http://example.org/has https://jorge.pod.ideniox.com/outbox/123123231123 .
https://jorge.pod.ideniox.com/outbox/123123231123 https://example.org/message ā€œā€ā€œHi!ā€"".
ļ»æ
Built a row function to read the above ttl.

const readTTL = url => {
return new Promise((resolve, reject) => {
try {
const store = $rdf.graph();
const fetcher = $rdf.fetcher(store, {fetch: auth.fetch.bind(auth)})
fetcher.load(url).then(() => {
const query = SELECT DISTINCT ?s WHERE { ?s ?p ?o . } ;
let resultSet = [];
let preparedQuery = $rdf.SPARQLToQuery(query, false, store);
store.query(preparedQuery, e => {
resultSet.push(e)
}, undefined, () => {
resolve(resultSet)
});
});
} catch (e) {
reject(e);
}
})
};

And I get the following output, which is not correctā€¦

0: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
1: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
2: [?o: Collection, ?p: NamedNode, ?s: BlankNode]
3: [?o: BlankNode, ?p: NamedNode, ?s: BlankNode]
4: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
5: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
6: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
7: [?o: Literal, ?p: NamedNode, ?s: BlankNode]
etcā€¦

Are you saying that the output is literally that, i.e. literally the string ā€œNamedNodeā€ as opposed to a NamedNode object? Because if itā€™s a NamedNode object, that is what Iā€™d expect the return to be. And Iā€™d expect to be able to get the subject NamedNodeā€™s value with what I showed in the example above: results[ā€™?sā€™].value.