Missed the BIND(?minCount AS ?mc) FILTER bound(?mc) suggestion, will try it now.

On Mon, Jul 6, 2020 at 12:56 PM Martynas Jusevičius
<[email protected]> wrote:
>
> Andy,
>
> This is getting quite complicated compared to the QuerySolutionMap. I
> get that we should rather be using alternatives, but you presented
> several and neither is a drop-in replacement for the QuerySolutionMap.
> I think Jena's documentation could use a section on this topic, with a
> comparison of the approaches and some criteria which should be used
> when, plus code examples.
>
> I am trying to build a VALUES block now. My code:
>
>     Map<String, RDFNode> subs = ...
>     Query query = QueryFactory.create(wrapper.getQuery().toString());
> // can't use wrapper.getQuery().cloneQuery() due to JENA-1935
>     List<Var> variables = subs.entrySet().stream().map(e ->
> Var.alloc(e.getKey())).collect(Collectors.toList());
>     List<Binding> values = subs.entrySet().stream().map(e ->
> BindingFactory.binding(Var.alloc(e.getKey()),
> e.getValue().asNode())).collect(Collectors.toList());
>     query.setValuesDataBlock(variables, values);
>
> First of all I am wondering why a substitution map
>
>     [( ?predicate = <http://spinrdf.org/spin#body> ), ( ?comment =
> "the body of the Template" ), ( ?minCount = 0 ), ( ?maxCount = 1 )]
>
>  produces the VALUES table of the form
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
>   ( spin:body UNDEF UNDEF UNDEF )
>   ( UNDEF "the body of the Template" UNDEF UNDEF )
>   ( UNDEF UNDEF 0 UNDEF )
>   ( UNDEF UNDEF UNDEF 1 )
> }
>
> and not simply
>
> VALUES ( ?predicate ?comment ?minCount ?maxCount ) {
>   ( spin:body "the body of the Template" 0 1 )
> }
>
>
> And then what do I do with expressions like FILTER (bound(?maxCount))
> which are used in SPIN's internal queries to "switch off" graph
> patterns (as I understand it) in the absence of the ?maxCount binding.
> It does not seem to have the same effect with VALUES.
>
>
>
>
> On Mon, Jul 6, 2020 at 11:28 AM Andy Seaborne <[email protected]> wrote:
> >
> > "bound()" is not a function in the strict sense.
> >
> > Another case where variables are necessary is "AS ?var"
> >
> > Long version:
> > https://afs.github.io/substitute.html
> >
> > The advantage of using VALUES or BIND to inject the substitution value
> > is that it preserves the original variable.
> >
> > Contrast the difference between these two:
> >
> >    QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> >    QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
> >
> > BIND(?minCount AS ?mc) FILTER bound(?mc)
> >
> >      Andy
> >
> > On 06/07/2020 09:56, Martynas Jusevičius wrote:
> > > The same problem (invalid query string) using
> > > QueryTransformOps.transformQuery().
> > >
> > > On Sun, Jul 5, 2020 at 11:34 PM Martynas Jusevičius
> > > <[email protected]> wrote:
> > >>
> > >> ParameterizedSparqlString does not work either (not related to bnodes).
> > >>
> > >> With a mapping ?minCount => 0, it produces an invalid query string:
> > >>
> > >> SELECT  (count(*) AS ?cardinality)
> > >>          WHERE
> > >>            { <http://spinrdf.org/spin#Templates>
> > >> <http://spinrdf.org/spin#body>  ?value
> > >>              FILTER bound(0)
> > >>            }
> > >>          HAVING ( ?cardinality < 0 )
> > >>
> > >> On Sun, Jul 5, 2020 at 10:31 PM Andy Seaborne <[email protected]> wrote:
> > >>>
> > >>>
> > >>>
> > >>> On 05/07/2020 20:36, Martynas Jusevičius wrote:
> > >>>> Thanks for the explanation.
> > >>>>
> > >>>> What do you mean with "inject" in 1/? ParameterizedSparqlString?
> > >>>
> > >>> initialBinding is done by making the starting condition for execution a
> > >>> binding of the variables instead of the empty root. (This works nearly
> > >>> always but is affected by variable name scopes - scopes, like subquery,
> > >>> didn't exist when the mechanism was introduced.
> > >>>
> > >>> ParameterizedSparqlString builds which is parsed so you should be able
> > >>> to put in <_:....>.
> > >>>
> > >>>       Andy
> > >>>
> > >>>>
> > >>>> On Sun, Jul 5, 2020 at 8:53 PM Andy Seaborne <[email protected]> wrote:
> > >>>>>
> > >>>>> <_:label> is a syntax feature, not built into the storage or query
> > >>>>> execution.
> > >>>>>
> > >>>>> model.createResource("_:" + id));
> > >>>>>
> > >>>>> creates a resource with a strange URI (which is actually illegal by 
> > >>>>> RFC
> > >>>>> 3986/7).
> > >>>>>
> > >>>>> There are various ways:
> > >>>>>
> > >>>>> 1/ The app can put the bnode into the QSM and injected at execution - 
> > >>>>> it
> > >>>>> won't become a bnode-variable because that happens in parsing.
> > >>>>>
> > >>>>> 2/ To put a concrete node into a query:
> > >>>>>
> > >>>>> String bn = "<_:" + id+">";
> > >>>>>
> > >>>>> then put string into SPARQL syntax:
> > >>>>>
> > >>>>> QueryFactory.create("SELECT * { VALUES ?s {"+bn+"} ?s ?p ?o }");
> > >>>>> QueryFactory.create("SELECT * { "+bn+" ?p ?o }");
> > >>>>>
> > >>>>> 3/ rewrite the abstract syntax after parsing:
> > >>>>>
> > >>>>> Map<String, Resource> substitutions =
> > >>>>>      Collections.singletonMap("s", bnode);
> > >>>>> query = QueryFactory.create("SELECT * { ?s ?p ?o }");
> > >>>>> query = QueryTransformOps.transformQuery(query, substitutions);
> > >>>>>
> > >>>>> Forms 2 and 3 have the advantage of not relying on how execution 
> > >>>>> works -
> > >>>>> QSMs are ingested inthe start of execution and e.g. aren't visible in
> > >>>>> subqueries and also interact and bypass with query optimization.
> > >>>>>
> > >>>>>        Andy
> > >>>>>
> > >>>>> On 05/07/2020 15:22, Martynas Jusevičius wrote:
> > >>>>>> Hi,
> > >>>>>>
> > >>>>>> I came across a situation where I want to carry over a blank node ID
> > >>>>>> in a QuerySolutionMap to QueryExecution, to match exact blank node
> > >>>>>> resources rather than have them as variables.
> > >>>>>>
> > >>>>>> I found an old thread by Holger on this topic:
> > >>>>>> https://mail-archives.apache.org/mod_mbox/jena-users/201308.mbox/browser
> > >>>>>>
> > >>>>>> The suggestion was to use <_:LABEL> URI scheme for blank nodes.
> > >>>>>> https://jena.apache.org/documentation/query/extension.html#blank-node-labels
> > >>>>>>
> > >>>>>> Based on that, I tried this logic:
> > >>>>>>
> > >>>>>>        if (instance.isURIResource()) qsm.add(SPIN.THIS_VAR_NAME, 
> > >>>>>> instance);
> > >>>>>>        if (instance.isAnon()) qsm.add(SPIN.THIS_VAR_NAME,
> > >>>>>> model.createResource("_:" + instance.getId()));
> > >>>>>>
> > >>>>>> However I'm not getting the results I expect. So I decided to make an
> > >>>>>> isolated test:
> > >>>>>>
> > >>>>>>        @Test
> > >>>>>>        public void bnodeQueryTest()
> > >>>>>>        {
> > >>>>>>            Model model = ModelFactory.createDefaultModel();
> > >>>>>>            Resource bnode = 
> > >>>>>> model.createResource().addProperty(FOAF.name,
> > >>>>>> "whateverest");
> > >>>>>>            AnonId id = bnode.getId();
> > >>>>>>
> > >>>>>>            Query query = QueryFactory.create("SELECT * { ?s ?p ?o 
> > >>>>>> }");
> > >>>>>>            QuerySolutionMap qsm = new QuerySolutionMap();
> > >>>>>>            qsm.add("s", model.createResource("_:" + id));
> > >>>>>>
> > >>>>>>            try (QueryExecution qex = 
> > >>>>>> QueryExecutionFactory.create(query,
> > >>>>>> model, qsm))
> > >>>>>>            {
> > >>>>>>                ResultSet resultSet = qex.execSelect();
> > >>>>>>
> > >>>>>>                assertTrue(resultSet.hasNext());
> > >>>>>>                assertEquals(id, 
> > >>>>>> resultSet.next().get("s").asResource().getId());
> > >>>>>>            }
> > >>>>>>        }
> > >>>>>>
> > >>>>>> The test fails on assertTrue() because SELECT returns no results.
> > >>>>>>
> > >>>>>> Is the test flawed? Am I misunderstanding the use of this URI scheme?
> > >>>>>> If not, what's the purpose if it cannot match blank nodes in data?
> > >>>>>>
> > >>>>>> Martynas
> > >>>>>>

Reply via email to