Updating only inputted fields - node.js

I'm making a RESTful API but I have run into some trouble. I want to update a row with only the values that have been passed through. So with the same endpoint the user can edit just the 'name', both the 'name' and 'type' or only the 'type'.
Here is a snipped of what I currently have:
Group.update({
created_by: req.user._id,
_id: req.params.group_id
}, {
name: req.body.name,
$addToSet: { users: req.body.users }
},
I'd like to make it so that if no users are passed through or no name is passed through it would still the update the other value. Could anyone point me in the right direction please?
Thanks,
Daniel

You need to build the query dynamically.
var find = {
created_by: req.user._id,
_id: req.params.group_id
}
var update = {};
if(req.body.name) {
update.name = req.body.name;
}
if(req.body.users) {
update['$addToSet'] = {};
update['$addToSet'].users = req.body.users;
}
Group.update(find, update, callback);
Its not the prettiest way but it should give you an idea of how to tackle this.

Related

How to remove a certain position from an array of objects that matches a value in Mongoose?

Is the first time I am working with backend (Mongoose, express, nodeJs). I have a collection of users in MongoDB.
I am sending the favoriteId from frontend and getting it in the backend. I want to delete the position of the array that matches with the favorite Id I am passing to the function.
I have tried several ways to remove the favorite using the $pull operator and the favoriteId but none work. So I don't know how to do it.
I would appreciate if someone could help me.
This is structure in MongoDB:
_id: new ObjectId("63"),
username: 'test1',
email: 'test1#gmail.com',
favorites: [
{
id: '25',
version: 'version3',
team: 'team1',
},
{
id: '27',
version: 'version2',
team: 'team4',
}```
This is my controller function:
```export const removeFavorite = async (req, res) => {
//Here I have the user Id 63
const userId = req.params.userId;
//here I have the favorite Id I Want to remove : 25
const favoriteId = req.body.params.id;
// Here I select the user in the collection
const deleteFavorite = await User.findOne({ _id: userId });
// Here I want to remove the favorite that matches with favoriteId (25)
res.status(200).json('ok');
};```
Try this:
User.update({ _id: userId }, { $pull: { 'favorites': { 'id': favoriteId } } });

Typeorm Query Builder filtering multiple columns with one value

My aim is to hit api endpoint and only pass one query variable and try to filter out any of the columns based on single variable.
I have multiple users in database like:
{
id: 1,
email: 'test+1#test.com',
username: 'test',
phone_number: '+651231231',
skillsets: 'Drawing, cooking',
hobby: 'Sleeping',
},
{
id: 2,
email: 'test+2#test.com',
username: 'test 2',
phone_number: '+6512312311231',
skillsets: 'Drawing, cooking',
hobby: 'Drawing',
}
My function/Query
let users = this.repo.createQueryBuilder('user');
if (query && query !== '') {
users = users
.where('user.email like :email', { email: `%${query}%` })
.orWhere('user.username like :username', {
username: `%${query}%`,
})
.orWhere('user.phone_number like :phone_number', {
phone_number: `%${query}%`,
})
.orWhere('user.skillsets like :skillsets', {
phone_number: `%${query}%`,
})
.orWhere('user.hobby like :hobby', { hobby: `%${query}%` });
}
return users.getMany();
My api endpoint would be something like
/api/users?query=Sleeping
I can't filter by anything else other than email and I assumed is because of initial where but I am not entirely sure how to cater for this scenario.
I appreciate if anyone can point me to the right direction.
I was looking to implement something similar and I found the answer in another Stackoverflow Question
It is possible to use OR clause using the simple typeorm .find() options as described in TypeORM docs.
To query with OR operator you'll need to use an array of conditions instead of an object.
let users = await user.find({
where: [
{ email: Like(%${query}%) },
{ skillsets: Like(%${query}%) },
{ username: Like(%${query}%) }
]
});
You can try something like this. Just add the other columns.
users = users
.where('user.email like :query AND (user.username like :query OR user.phone_number like :query)', { query: `%${query}%` })
You can use setParameter function from the query builder, and use the value wherever you pass the key of the parameter.
So maybe you can improve your code like this:
const users = this.repo.createQueryBuilder('user');
if (query) {
users
.where('user.email LIKE :query')
.orWhere('user.username LIKE :query')
.orWhere('user.phone_number LIKE :query')
.orWhere('user.skillsets LIKE :query')
.orWhere('user.hobby LIKE :query')
.setParameter('query', `%${query}%`);
}
return users.getMany();
Hope this helps.

How to create a delete method in nodejs(express) with sequelize(sqlite) as database

I have been trying yesterday and still continuing today to figure out how to create a nodejs delete method so I can delete data from database based on ID.
I have tried different code from google/youtube/stackoverflow etc but nothing has worked so far.
The error I have with this code is that data.query is not a function. Data is a variable on my code.
If anyone has any idea how to fix please help.
app.js
app.delete('/zoom/:id', function(req, res) {
data.query('delete from', [req.params.id]);
res.render('deleted')
});
data.js
var Data = sequelize.define('data', {
subject: Sequelize.STRING,
MEETINGID: Sequelize.STRING,
Password: Sequelize.STRING
});
Sequelize destroy method seems like a suitable one. E.g.
app.delete("/zoom/:id", function (req, res) {
data.destroy({
where: {
// criteria
},
});
res.render("deleted");
});
To set a criteria which i suitable for your situation, you will need to take a look at sequelize syntax. I found some examples and may be you can modify them to your needs. Depending on your database structure.
where: {
'$car.id$': 2
},
where: {
furniture_type: 'leather'
},
where: {
id: {
$notLike: { $any: someValue }
}
},

Not able to persist array of objects in mongo using mongoose

I'm trying to persist an array of objects in a document using mongoose. I have tried multiple times but it's not persisting array in document. It places an empty array in document.
Following is my Schema:
var ProfileSchema = new Schema({
name: String,
PagesData: [{
pageAccessToken: {type: String, get: decryptText, set: encryptText},
category: String,
name: String,
id: String,
perms: [String]
}]
});
module.exports = mongoose.model('Profile', ProfileSchema);
I'm trying to save a document with an array of objects using following query:
var newProfile = new Profile();
newProfile.name = "someName";
newProfile.PagesData = [ { pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms:
[ 'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT' ] } ];
newProfile.save(function(err, result, numAffected){
if(err) {
console.log(err);
res.send(500, "Error");
}
console.log(result);
res.send(200, "Success");
});
I tried debugging the mongo commands using
require('mongoose').set('debug', true)
On Debug logs it shows, empty array during insert command execution.
Can anyone please tell me how can I store this array of object in my schema ?
Thanks,
Update:
It's been too long and I'm still not able to figure out the root cause of the problem. There is a long thread going on github for this.
https://github.com/Automattic/mongoose/issues/3249
I would like other experts to please take a look and suggest me some way by which I can solve the issue. I'm really stuck at this.
Update 2:
None of the solution worked for me so far, so I decided to modify the schema only to meet my requirements. This resulted in a different problem:
I want to create a map with a objectId as key and an array of string values as its value. The closest that I can get is:
var schema = new Schema({
map: [{myId: {type:mongoose.Schema.Types.ObjectId, ref: 'MyOtherCollection'}, values: [String]}]
});
But somehow this is not working for me. When I perform an update with {upsert: true}, it is not correctly populating the key: value in the map. In fact, I'm not even sure if I have declared the schema correctly.
Can anyone tell me if the schema is correct ? Also, How can I perform an update with {upsert: true} for this schema?
Also, if above is not correct and can;t be achieved then how can I model my requirement by some other way. My use case is I want to keep a list of values for a given objectId. I don't want any duplicates entries with same key, that's why picked map.
Please suggest if the approach is correct or should this be modelled some other way?
Thanks
I tried the exact code you have provided here and it's working for me. I am not sure what is causing the issue for you. Until and unless we get the same issue, it's very difficult to rectify it.
Here are few suggestions which you might try:
Create a simple schema and try storing the object, that way you can
figure it out if it has to do something with the schema.
You can try out your schema in a sample app to find if some
dependency is causing the problem.
Once you know where exactly the problem is, you would be able to figure out a solution too. I hope it helps.
I tested this and the insert works for me using the below:
(I had to remove the get: decryptText, set: encryptText)
var n = { name: "Testing for mongoose", PagesData : [{ pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms:
[ 'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT' ] } ] }
Profile.create(n, function (err) {
if (!err) {
return 'records saved successfully';
}
else {
return error on save:' + err;
}
});
To create multiple pageDatas you can use it as an embedded collection instead of using arrays.
The Schema will be as follows:
var PagesDataSchema = new Scheme({
pageAccessToken: {type: String, get: decryptText, set: encryptText},
category: String,
name: String,
id: String,
perms: [String]
})
var ProfileSchema = new Schema({
name: String,
PagesData: [PagesDataSchema]
});
module.exports = mongoose.model('Profile', ProfileSchema);
Reference: http://mongoosejs.com/docs/subdocs.html
For Saving the document you can use like.
exports.save = function(req,res){
var test = new ProfileSchema; // new object for ProfileSchema domain.
test.name= req.body.name;
if(req.body.PagesData){
req.body.PagesData.forEach(function(page){ // For every element of pageData from client.
test.PagesData.push(page) // This pushes each and every pagedata given from the client into PagesData.
})
}
test.save(function (saveErr, saved) { // Saves the new document into db.
if (saveErr) {
console.log(saveErr)
return;
}
res.status(HttpStatus.OK).json(saved);
});
};
Hope this helps.
Have you tried
Profile.create({
name: "someName",
PagesData: [
{
pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms: [
'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT'
]
}
]
}, function(err, profile) {
// do your stuff
})
?

Node.js How to republish the data.

We have published items based on list ids , we use myLists variable to filter out the List Id, but this variable is not reactive by nature ,when we try to add the new list , then items of new list are not publishing automatically.
Meteor.publish('subscription_items', function () {
var userName = this.userId ? Meteor.users.find({ _id: this.userId }).fetch()[0].username : null;
var myLists = [];
var sharedListIDs = [];
SharedLists.find({ shared_with: userName }).forEach(function (list) {
sharedListIDs.push(list.list_id);
});
Lists.find({ $or: [{ owner: userName }, { _id: { $in: sharedListIDs } }] }).forEach(function (list) {
myLists.push(list._id);
});
return Items.find({ list_id: { $in: Lists.find({ $or: [{ owner: userName }, { _id: { $in: sharedListIDs } }] }).fetch() } });.
Can we have any way to always publish fresh data. Please help me to resolve this issue. any help/suggestion would appreciate.
As David Weldon pointed out in this answer to my similar question, what you are looking for is a reactive join. By using the package publish-with-relations, I think the publish function you want looks something like this:
Meteor.publish('subscription_items', function() {
return Meteor.publishWithRelations({
handle: this,
collection: Lists,
filter: {owner: this.userId},
mappings: [{collection: SharedLists, key: 'list_id'}]
});
});
Alternatively, as a (dirty) workaround, you could call
Meteor.subscribe('subscription_items');
everywhere where you need the collection to be republished.

Resources