strongloop / loopback

LoopBack makes it easy to build modern applications that require complex integrations.
http://loopback.io
Other
13.23k stars 1.2k forks source link

mapping query syntax to other dialects? #493

Closed HansHammel closed 10 years ago

HansHammel commented 10 years ago

Is it possible to map (declarative) the existing (qs-based) filters/ queries to other dialects (esp. popular datagrids like jquery datatables, jqGrid, Kengo UI, Ingnite UI and Sencha Grids, w2grid, dhtmlxGrid, FlexGrid, EditableGrid, etc.)? Unfortunately there are many dialects/ query syntaxes out there so I think this is an essential feature to make the most of loopbacks autowiring!

fabien commented 10 years ago

I believe this mapping should happen at the client-side, but you can always register a beforeMethod to parse out the request options you need - something like:

MyModel.beforeRemote('find', function(ctx, result, next) {
   var myParam = ctx.req.param('my');
   ctx.args['filter'] = ctx.args['filter'] || {};
   ctx.args['filter']['offset'] = parseInt(myParam, 10);
   next();
});
HansHammel commented 10 years ago

But how can I profit from the build in filters that way? You know, without reinventing the wheel... Update: OK. Just tested. I think I can solve my pagination issue that way. And, I think, the boilerplate code for more complex filters like comparators is minimal. Thanks. Any chance to apply such "adaptors" to multiple models in a declarative way? Maybe a global model hook, like extending the model definition and parsing the name and applying a certain "adaptor"?

fabien commented 10 years ago

@HansHammel I think you can apply these before/after remote hooks like this too:

// in a boot script at /server/boot
var remotes = app.remotes();
remotes.before('**', function(ctx, next, method) {
  var req = ctx.req;
  var Model = method.ctor;
  var modelInstance = ctx.instance;
  if (Model.modelName === 'MyModel') {
    …
  }
  next();
});
raymondfeng commented 10 years ago

Please note we support stringified json value too. One solution is that you can normalize the query params on the client side.

BTW, I think Ritchie has proposed to add ‘style’ support for url conventions. We can extend it to query parameter parsing. This way, we can allow the customization for the loopback.rest() middleware.

Thanks,


Raymond Feng Co-Founder and Architect @ StrongLoop, Inc.

StrongLoop makes it easy to develop APIs in Node, plus get DevOps capabilities like monitoring, debugging and clustering.

On Aug 25, 2014, at 4:57 AM, Fabien Franzen notifications@github.com wrote:

@HansHammel I think you can apply these before/after remote hooks like this too:

// in a boot script at /server/boot var remotes = app.remotes(); remotes.before('**', function(ctx, next, method) { var req = ctx.req; var Model = method.ctor; var modelInstance = ctx.instance; if (Model.modelName === 'MyModel') { … } next(); }); — Reply to this email directly or view it on GitHub.

HansHammel commented 10 years ago

Well, better control over parameters is always a good thing, but for now, the remote before hook ^^ works perfectly fine with jqGrid (sorting, filtering, even multi column filtering works for me now). So, writing a server side adaptor using the hooks seems (currently) to be the best bet for me.

By the way, thanks!

But, a declarative way of connecting the major components remains the goal to pursue. I am not yet sure if and how it could be done, because mapping the different query syntaxes is a quite complex task. The declarative way may require some weird extensions to the loopback model definition language and the general capabilities of loopback (like jqGrid is aware of a "is not null" filter, among others).

Apropos, where can I find this "offset filter"? The only build in filters mentioned in the docs are: fields, include, limit, order, skip and where? Are there more undocumented filters? Where is the context object described? Can I access custom fields from the models json?

TL;DR Sad to say, but some grid components are not flexible enough to do the necessary changes, easily. Well, by nature, everything in JS is customizable, but as I always say we don't want to reinvent the wheel like using the "correct" HTTP verbs (easy to fix client side) or supporting filters, not (yet) present in loopback (obviously impossible to fix client side). Well, the last one points out the crux. Displaying data with e.g. jQuery Datatables is one of the most common tasks out there. So, a real versatile API server, needs to ship (IMHO) with a couple of those adaptors to outpace competitors by versatility (supported components) and ease of use (declarative usage), saving thousands of developers billions ;-) of hours of work on glue code...

fabien commented 10 years ago

Yes, customizing client-side libs can be quite painful. The remoting hooks help, but it's not exactly declarative. But implementing this can get complicated quickly.

A way to customize loopback's parameter parsing using some callback function(s), seems to be more appropriate. Usually it's much easier and probably even less verbose than inventing some kind of DSL for this mapping.

PS if you don't mind using Backbone - here's a highly customizable grid: http://backgridjs.com/ (using https://github.com/backbone-paginator/backbone.paginator internally, which is also able to map to any kind of pagination api).

Apropos, where can I find this "offset filter"? The only build in filters mentioned in the docs are: fields, include, limit, order, skip and where?

The offset parameter is the same as skip. We're already mapping it to both keys, to more closely match some of the terms out there (skip is mongo-speak, offset is common in SQL).