-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Creating a batchloader for belongsToMany relationships #6
Comments
feathers-plus/cli-generator-example has several many-to-many entities. You can look at that. If your many-to-many file contains { a, b } and a base record contains 'a' then you would join all the 'a' records to in { a, b } to the base record, and for such { a, b } you would join whatever record 'b' referes to. |
Reopen this if you have more questions. |
Thank you for the reply. I found the examples quite confusing though, mainly because I'm new to Feathers, don't understand all the concepts yet and the code in those examples is so different from whats written in the BatchLoader guide. E.g. in the examples a However after spending several hours more today, I managed to get something working which is probably terrible. :) Instead of using the loaderFactory I created a custom BatchLoader which looks like follows: const BatchLoader = require('@feathers-plus/batch-loader');
const { loaderFactory, getUniqueKeys } = BatchLoader;
const { omit } = require('lodash')
context._loaders.assignees.task_id = new BatchLoader(async (keys, context) => {
// batch loader function for belongsToMany task <-> assignee relationship
const taskModel = context.service.Model;
const users = context.app.service('users');
const assignees = await users.Model.findAll({
include: [{
model: taskModel,
as: 'tasks',
where: {
id: {
$in: getUniqueKeys(keys)
}
},
}],
raw: false
});
// prepare an array of same length as keys
var result = new Array(keys.length).fill(null).map(() => []);
assignees.forEach((user) => {
user.tasks.forEach((task) => {
let idx = keys.indexOf(task.id);
// check if user already exists
if(result[idx].map(user => user.id).indexOf(user.id) === -1) {
// create new user object and delete tasks
// so in the final output all user tasks are not displayed
// again (avoid circular structure)
var newUser = JSON.parse(JSON.stringify(user));
newUser = omit(newUser, ['tasks']);
// add to result
result[idx].push(newUser);
}
});
});
return result;
}, {context}); |
loaderFactory is just a convenience method handling the most common case. It's also useful in making examples easier to understand. No need to use it if your needs differ. |
You implementation is a good example that batchloaders can be as complicated as necessary. |
Do you see anything obvious that could be improved upon in the example? There are a few things that feel ugly-ish to me, mainly:
|
Hello,
this is not a bug, but maybe the documentation could be expanded upon as I could find anything. In my app I have tasks and users. Each tasks is assigned to several users and a user can have several tasks. So we have a belongsToMany (n:m) relationship on both sides.
Does batchloading work for this scenario? I'm a bit clueless how to get it working in that case. is there an example somewhere I could get inspiration from?
Regards
The text was updated successfully, but these errors were encountered: