From: Tomasz P. <tom...@gm...> - 2012-10-18 18:35:27
|
Hi Rob Actually I have just today been preparing an email to agree on the fluent API. Here it goes. I have been thinking about the shape of the fluent query API and I would like to propose some changes. 1. Currently there are quite a few overloads of the Where method. I think the API will be more usable if we left only a limited number, eg. * IQueryBuilder#Where(params ITriplePattern[] patterns) * IQueryBuilder#Where(params Triple[] triples) - not sure about triples here though * IQueryBuilder#Where(GraphPattern) Regarding the ast overload, what are the ways to create graph patterns? I mean I have seen the ToGraphPattern() method here and there. Which classes define such a method and what are differences in the graph patterns they produce? 2. I think the API should expose functionality but with least required use of the internal SPARQL types like the ITriplePattern, ISparqlExpression and such. I would not remove it of course to leave room for flexibility. For a day-to-day query building I think that maybe creating triple patterns should be split into subjects, predicates, object and possibly graphs (here this posin overlaps the above about GraphPatterns). As such it sould be possible to implement less code and at the same time give a greater flexibility for the user and remove the burden of creating instances of the SparqlVariable class and such. For example: var prefixes = new NamespaceMapped(); // set up prefixes ... IQueryBuilder query = QueryBuilder.Select("person", "name"); // I have just made this up, but could be useful although string name interfere with // QNames. Maybe add a struct QName? query.UsePrefixesFrom(prefixes); 2a. // a more flexible form of triple pattern building // note the RdfType mehod. This way it would could provide some common // properties/classes and also leave an opening for users to create their own extension methods query.Where.Subject("person").RdfType().Object(new QName("foaf:Person")); 2b. // alternatively there's a proposal without the QName struct/class, which I like more query.Where.Subject("person").RdfType().Object<IUriNode>("foaf:Person")); 2c. // here NodeMatchPattern for predicate with full Uri given and obejct as a VariablePattern query.Where.Subject("person").Predicate(new Uri("http://xmlns.com/foaf/0.1/name")).Object("name")); In terms of graphs, I think that maybe we could provide one more method to such ITripleVariable-producing chain, to select the appropriate named graph pattern 2d. query.Where.Subject("person").Predicate(new Uri("http://xmlns.com/foaf/0.1/firstName")).Object("name")).InGraph(new Uri("http://uri/of/graph")); query.Where.Subject("person").Predicate(new Uri("http://xmlns.com/foaf/0.1/lastName")).Object("surname")).InGraph(new Uri("http://uri/of/graph")); query.Optional.Subject("person").Predicate<IUriNode>("foaf:mbox_sha1sum").Object("emailSha1")).InGraph(new Uri("http://uri/with/contact/data")); All the above would produce: ad 2a/2b and 2c WHERE { ?person a foaf:Person . ?person foaf:name ?name . } ad 2d WHERE { # calling InGraph() with same parameter should # add triple pattern to same graph pattern, right? GRAPH <http://uri/of/graph> { ?person foaf:firstName ?name ?person foaf:lastName ?surname } GRAPH <http://uri/with/contact/data> { OPTIONAL { ?person foaf:mbox_sha1sum ?name } } } Not how the OPTIONAL has API equivalent to WHERE 3. I have also been thinking that a simmilar way could be used to create CONSTRUCT queries. However with the current static initialization of query builder I would suggest slightly modifying the above to reuse the same methods in both scenarios One way I find quite good could be using an Action<> delegate and introducing an ITriplePatternBuilder interface to actually build the triple patterns: var query = QueryBuilder.Construct( (ITriplePatternBuilder tp) => tp.Subject("person").RdfType().Object<IUriNode>("ex:MyPersonClass") ); With this approach, the Where/Optional would change to: query.Where( tp => tp.Subject("person").RdfType().Object<IUriNode>("foaf:Person")) ); and internally bouth would look somewhat like: public IQueryBuilder Where(Action<ITriplePatternBuilder> buildTriplePatterns) { var builder = new TriplePatternBuilder(); //implementation internal buildTriplePatterns(builder); return Where(builder.TriplePatterns.ToArray()); } I think this way we get a clean seperation of concerns, good testability and room for extensibility. 4. Ask query is trivial. The SPARQL update could also use the proposed ITriplePatternBuilder I think 5. Basic federated queries could be achived in a simmilar way the InGraph() method is used above for 6. We need a method for the BIND keyword, eg. public IQueryBuilderBind(ISparqlExpression expression, string variableName) { ... } Oh well, there is much more, but we have enough to discuss just for now. Tell me what are your feelings about all the above. You are certainly more experienced with SPARQL so I would be greateful for your own ideas for this feature, which I'm sure you have :). Also, what do you think would be the greatest challenges here? Thanks, Tom On Thu, Oct 18, 2012 at 7:04 PM, Rob Vesse <rv...@do...> wrote: > Hey Tom > > Can you send me a pull request for what you have so far on the fluent-query > branch? > > I've finished up the refactor I was working on so have some more time to > look at the fluent-query work if you'd like some help > > Cheers, > > Rob > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_sfd2d_oct > _______________________________________________ > dotNetRDF-develop mailing list > dot...@li... > https://lists.sourceforge.net/lists/listinfo/dotnetrdf-develop > |