sequelize has many associations update - mysql

i am building resful api with node js and sequelize (mysql).
i have two models with (event) has many (users).
for creating event with models i am doing this :
add(req, res) {
return event.create(
{
name: req.body.name,
users: req.body.users,
},
{
include: [
{
model: User,
as: "users",
},
],
}
)
it's working fine .
but when i want to update i have big issue here.
for example my current events looks like :
"events" : [
{
"id" : 1 ,
"name" :"name"
"users" :[
{
"id" :1 ,
"name" :"name1",
},
{
"id" :2 ,
"name" :"name2",
}
]
}]
what i want to achieve :
i want to update users :
if the id of user exists in the request i want to update the user ,but if the id doesn't exists in the request i want to delete do user.
how i can do that in sequelize and node js .i'm stack here.

Show your router where you try to handle that logic.
When you say that user exists do you mean user exists at all or only belongs to requested event, please be more specific!!!
// lets say you want to update users of event id=1
const event = await Event.findByPk(1)
// you can get users belonging to event by association mixins
const users = await event.getUsers()
// loop through users to update them
for (let i=0; i < users.length; i++) {
// put your logic to make changes to users
if (users[i].getDataValue('id') == 1) {
await event.removeUser(users[i])
}
}

Related

How to do a relatedQuery (many2many) with feathers-objection

Regarding to this post: https://stackoverflow.com/a/69903276/1547821
it shows an approach with less boilerplate, to prevent a users query output (GET) to only the user who is logged in.
But how to do this, to get i.e. all members of the related group which the logged-in user participates?
This example below is my hook, but i want to have it in before->find hook as a query injection or addition.
module.exports = (options = {}) => {
return async context => {
const groupMembers = await context.app.service('groups').options.model.relatedQuery('users').for(context.params.user.id)
console.log(groupMembers)
return context
}
}
It doesn't help me as after->find hook, because total and etc. doesn't match then. Aswell my keeps doesn't work.
Appreciating any hints.
One solution would be to add a userId column to your groups model. This will contain a user of the group.
//in your /services/groups.hook.js
const { authenticate } = require('#feathersjs/authentication').hooks;
const { setField } = require('feathers-authentication-hooks');
module.exports = {
before: {
all: [],
find: [
authenticate('jwt'),
setField({
from: 'params.user.id',
as: 'params.query.userId',
}),
],
get: [],
create: [],
update: [],
patch: [],
remove: [disallow('external')],
},
//after and error options go here
};
This should return only results where the logged in user's Id matched the Id in the group table.
Ps: try console logging the context object for more insight. Also the userId column in groups model should be associated to the id column of users model.
Thanks. Meanwhile I found a solution for the before->find.hook:
context => {
if(context.params.user !== undefined) {
const groupMembers = await context.service.options.model.relatedQuery('groups').for(context.params.user.id)
if(groupMembers) {
context.params.query['$joinEager'] = 'groups'
context.params.query['groups.id'] = groupMembers[0].id
}
}
return context;
};

Include ressource link in Sequelize result

I'm building a rest api that uses Sequelize to interact with the database. A query looks like this:
function read_category(req, res) {
Category.findById(req.params.categoryId, {rejectOnEmpty: true}).then(category => {
res.json(category);
}).catch(Sequelize.EmptyResultError, function () {
res.status(404).json({message: 'No category found'});
}
).catch(function (err) {
res.send(err);
}
);
}
Now I want the category object that is returned from Sequelize and then returned to the user to include the linkto the ressource. I could do:
category.dataValues.link = config.base_url + 'categories/' + category.dataValues.id;
Which would result in:
{
"id": 1,
"name": "TestCategory 1",
"position": 1,
"createdAt": "2018-08-19T11:42:09.000Z",
"updatedAt": "2018-08-19T11:42:09.000Z",
"link": "http://localhost:3000/categories/1"
}
Since I have more routes than this one I'm wondering if there's a dynamic way to add the link property to every category. I don't want to save it in the database because the base-url might differ.
Thanks!
Better way to do it is , create a getter method :
const Category = sequelize.define( 'category' , {
....
your_fields
....
},
{
getterMethods:{
link() {
return config.base_url + 'categories/' + this.id;
}
}
});
module.exports = Category;
Then
Category.findAll(...).then(categories => {
// Now there is no need to append data manually , it will added each time when you query
console.log(categories); // <-- Check the output
})

Firebase + Aurelia: how to process the returned key=>value format by Firebase?

I'm retrieving the following structure from Firebase:
"bills" : {
"1" : { // the customer id
"orders" : {
"-KVMs10xKfNdh_vLLj_k" : [ { // auto generated
"products" : [ {
"amount" : 3,
"name" : "Cappuccino",
"price" : 2.6
} ],
"time" : "00:15:14"
} ]
}
}
}
I'm looking for a way to process this with Aurelia. I've written a value converter that allows my repeat.for to loop the object keys of orders, sending each order to an order-details component. The problem is, this doesn't pass the key, which I need for deleting a certain order ("-KVMs10xKfNdh_vLLj_k")
Should I loop over each order and add the key as an attribute myself?
Is there a better/faster way?
This answer might be a little late (sorry OP), but for anyone else looking for a solution you can convert the snapshot to an array that you can iterate in your Aurelia views using a repeat.for, for example.
This is a function that I use in all of my Aurelia + Firebase applications:
export const snapshotToArray = (snapshot) => {
const returnArr = [];
snapshot.forEach((childSnapshot) => {
const item = childSnapshot.val();
item.uid = childSnapshot.key;
returnArr.push(item);
});
return returnArr;
};
You would use it like this:
firebase.database().ref(`/bills`)
.once('value')
.then((snapshot) => {
const arr = snapshotToArray(snapshot);
});

MySQL multiple related permission per one user in the same result possible?

I am using sequalize in a nodeJs application. I have an entity with a one to may relation (user to many permissions).
I have the following sequalise query to get all users with their permissions... but i think i have been in nosql land for too long :/ and i fear my head no longer works in this way...
models.User.findAll( {
raw: true,
include: [ {
model: models.UserPermissions,
required: false
} ],
logging: console.log
} ).then(function( users ) {
deferred.resolve( users );
}, function(err) {
deferred.reject(err);
});
Produces the following mysql query:
SELECT
`User`.`id`,
`User`.`username`,
`User`.`password`,
`User`.`reset_password_token` AS `resetPasswordToken`,
`User`.`reset_password_expires` AS `resetPasswordExpires`,
`User`.`created_at`, `User`.`updated_at`,
`UserPermissions`.`id` AS `UserPermissions.id`,
`UserPermissions`.`user_id` AS `UserPermissions.user_id`,
`UserPermissions`.`permission` AS `UserPermissions.permission`,
`UserPermissions`.`created_at` AS `UserPermissions.created_at`,
`UserPermissions`.`updated_at` AS `UserPermissions.updated_at`
FROM
`user` AS `User`
LEFT OUTER JOIN `user_permissions` AS `UserPermissions`
ON `User`.`id` = `UserPermissions`.`user_id`;
The result of course is not what I am no used with NoSQL. Instead of recieving one object containing the user and also an array of documents within containing the related permissions I get multiple results for the same user but with different permissions.
See the snapshot of the result set below (I have 2 users in the users table, and 3 permissions in the permissions table).
Is it possible with sequalise, or even mysql for that matter, to return one object for a user with a sub array of their pemissions? or will this really require another query and post query match up?
HACKY FIX:
models.User.findAll( {
raw: true,
include: [ {
model: models.UserPermissions,
required: false
} ]
} ).then(function( users ) {
var newUsersObj = {};
for( var i = 0 ; i < users.length ; ++i ){
if( newUsersObj[users[i].id] ){
newUsersObj[users[i].id].permissions.push( users[i]['UserPermissions.permission'] );
} else {
newUsersObj[users[i].id] = users[i];
newUsersObj[users[i].id].permissions = [ users[i]['UserPermissions.permission'] ];
}
}
deferred.resolve( newUsersObj );
}, function(err) {
deferred.reject(err);
});

How do you insert an array of object into Mongodb node.js

Basically i want to insert into my Mongodb collection called "Events" an array of objects called "Events" with an id for each entry into the array.
This is the result i want to get in json:
{
"events" : [
{
"_id" : ObjectId("53a99cc608ad49712a830081"),
"eTitle" : "Freshers Fair",
"eDesc" : "Bring some friends with you oh wait, you have non ha !",
"eDate" : "2014-06-19 11:20",
"eLink" : "http://fair.com",
"eEvent" : "NEFS"
},
{
"_id" : ObjectId("53a99cc608ad49712a830082"),
"eTitle" : "Blahh",
"eDesc" : "Blah fdinidf !",
"eDate" : "2014-06-19 11:20",
"eLink" : "http://google.com",
"eEvent" : "NEFS"
}
]
}
So far this is the result i have:
[
{
"_id":"53a9b5ed745363432d823d7a",
"eTitle":"jrnfdeiujn rd",
"eDesc":"grfdsreds",
"eDate":"2014-07-05 22:33",
"eLink":"reser",
"eEvent":"Victoria Center"
},
{
"_id":"53a9b771745363432d823d7b",
"eTitle":"Hello worlds",
"eDesc":"blah",
"eDate":"2014-07-20 22:33",
"eLink":"http://google.com",
"eEvent":"social"
}
]
This is how i insert data with node.js:
// Set our collection
var collection = db.get('Events');
// Submit to the DB
collection.insert({
"eTitle" : eTitle,
"eDesc" : eDesc,
"eDate" : eDate,
"eLink" : eLink,
"eEvent" : eEvent
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// If it worked, set the header so the address bar doesn't still say /adduser
res.location("eventlist");
// And forward to success page
res.redirect("eventlist");
}
});
So please i how do i make the format look this the first json format i provided. sorry for the nooby question, just started learning node ! Thanks alot
UPDATE
To post Events:
router.get('/eventlist', function(req, res) {
var db = req.db;
var collection = db.get('Events');
collection.find({},{},function(e,docs){
console.log(docs);
res.send(docs);
// res.render('eventlist', {docs: JSON.stringify(docs), title: 'Test'});
});
});
You can do this:
collection.find({},{},function(e,docs){
var doc = { Events : docs };
console.log(doc);
res.send(doc);
// res.render('eventlist', {docs: JSON.stringify(docs), title: 'Test'});
});