Comments (13)
You could add your own query parameter and make the model call based on that query in the hook, setting hook.result
similar to this:
app.service('users').before({
find(params) {
if(params.query.$distinct) {
return this.Model.find().distinct().then(data => {
hook.result = data;
return hook;
});
}
}
});
from feathers-rest.
Thanks so much for the quick response @daffl - By doing it this way, is my understanding correct that it would do 2 DB queries, where the second is unneeded?
from feathers-rest.
No. If you set the result in a before
hook the original database call is not going to happen.
from feathers-rest.
Wow, great to know. Thanks again!
I'll give it a go
from feathers-rest.
Hi @daffl - I ended up creating a hook like this, which seems to work a treat:
/*
* Distinct Search - can only be 1 distinct at a time
* - allows you to URI query like: books?$distinct=author
* ============================================================
*/
exports.searchDistinct = function () {
return function (hook) {
let query = hook.params.query;
// Must be a before hook
if (hook.type !== 'before') {
throw new Error('The \'searchDistinct\' hook should only be used as a \'before\' hook (hooks.searchDistinct).');
}
// Throw error when no field is provided - eg. just users?$distinct
if (query.$distinct === '') {
throw new Error('Missing $distinct: Which field should be distinct? (hooks.searchDistinct)');
}
let distinctValue = query.$distinct || null;
if (distinctValue == null) return hook;
// Remove $distinct param from query (preventing errors)
delete query.$distinct;
return new Promise((resolve, reject) => {
var args = [
{ $match: query || {} },
{ $group: {
_id: "$" + distinctValue,
total: { $sum: 1 }
}}
];
this.Model.aggregate(args)
.then(data => {
hook.result = {
total: data.length || 0,
data,
};
resolve();
}).catch(err => reject(err));
});
}
}
This allows you to hit an endpoint like /users?status=active&$distinct=country
and returns data similar to:
{
"total": 25,
"data": [
{
"_id": "Spain",
"total": 22
},
{
"_id": "Denmark",
"total": 12
}
...
from feathers-rest.
Awesome, thank you for sharing!
Oh, btw, you can probably just return this.Model.aggregate(args)
instead of having to create a wrapper promise.
from feathers-rest.
Thanks @daffl - that's true - although I have the wrapper promise so that I can alter the hook.result
to include a total
and if needed, later on extend to include $skip
and $limit
for example.
from feathers-rest.
What I meant is that you can write the same thing like this:
/*
* Distinct Search - can only be 1 distinct at a time
* - allows you to URI query like: books?$distinct=author
* ============================================================
*/
exports.searchDistinct = function () {
return function (hook) {
let query = hook.params.query;
// Must be a before hook
if (hook.type !== 'before') {
throw new Error('The \'searchDistinct\' hook should only be used as a \'before\' hook (hooks.searchDistinct).');
}
// Throw error when no field is provided - eg. just users?$distinct
if (query.$distinct === '') {
throw new Error('Missing $distinct: Which field should be distinct? (hooks.searchDistinct)');
}
let distinctValue = query.$distinct || null;
if (distinctValue == null) return hook;
// Remove $distinct param from query (preventing errors)
delete query.$distinct;
var args = [
{ $match: query || {} },
{ $group: {
_id: "$" + distinctValue,
total: { $sum: 1 }
}}
];
return this.Model.aggregate(args)
.then(data => {
hook.result = {
total: data.length || 0,
data,
};
return hook;
});
}
}
I found that especially when dealing with other calls that return a promise there is usually no need to create a new promise with new Promise((resolve, reject) => {})
from feathers-rest.
Ah hah! Very helpful, thank you!
from feathers-rest.
I'm going to try and keep this in mind for reference in case we want to roll this into some common hooks. cc/ @feathersjs/core-team
from feathers-rest.
I've tagged this as a todo for myself.
Please comment on any enhancements, changes, etc you have in mind.
from feathers-rest.
Hello
I need to create a hook like this one to rethinkdb database adapter. How can I do it?
thanks.
from feathers-rest.
I solved my problem like this.
let query = hook.params.query;
// Must be a before hook
if (hook.type !== 'before') {
throw new Error('El hook \'distinct\' sólo puede usarse como hook \'before\' (hooks.distinct).');
}
// Throw error when no field is provided - eg. just users?$distinct
if (query.$distinct === '') {
throw new Error('$distinct no encontrado: ¿Qué campo debería ser distinto? (hooks.distinct)');
}
let distinctValue = query.$distinct || null;
console.log('distinctValue', distinctValue);
if (distinctValue == null) return hook;
// Remove $distinct param from query (preventing errors)
delete query.$distinct;
// Add only the field we are searching for
query = Object.assign({ $select: distinctValue },query)
const rethinkdbQuery = this.createQuery(query);
const r = this.options.r;
// In our case, disable pagination
hook.params.paginate = false;
// Update the query with an additional `distinct` condition
hook.params.rethinkdb = rethinkdbQuery.distinct();
return hook;
from feathers-rest.
Related Issues (20)
- Consider how to handle file upload HOT 5
- Add headers and remote IP
- res.hook should exist in middleware after errors
- Setting 'content-type' header properly with boundary HOT 3
- $in: [] returning unexpected results HOT 2
- JSON-API + feathers-rest HOT 4
- Property 'axios' does not exist on type 'Transport' HOT 4
- $gte query example? HOT 2
- Map route parameters to `params.route` HOT 1
- How to return a pdf download file instead of data ?
- Update returning 204 HOT 2
- An in-range update of feathers is breaking the build 🚨 HOT 1
- Prepare for feathers v3 HOT 9
- Angular http implementation error HOT 1
- Client fails to parse json response on 204 status using fetch HOT 2
- $in operator doesn't work correctly through rest HOT 15
- fn.call is not a function(…) on client side with webpack HOT 2
- Client: Support Service Middleware / Generic Service HOT 5
- support axios? HOT 3
- Custom HTTP status code response HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from feathers-rest.