I have a NodeJS Express APP and I am building an endpoint to update Terms&Conditions
http://127.0.0.1:3000/api/admin/info/terms/de?version=2
However the text I'm trying to store is way too heavy (text has tabs, single and double quotes and so on), and requires a ton of editing in order to be placed in a json body {"terms":"easy text"}. {"terms": "heavy "text//"" that . "I dont" wish to""" editööäääÄÄ""}
What's the best way of handling this kind of text? Convert it to binary and then send it?
My endpoint
router.post('/terms/:language', async (req, res) => {
try {
const { language } = req.params;
const { version } = req.query;
const { terms } = req.body;
if (!version) return res.status(400).json({ message: 'Field "version" is empty' });
let info = await PageInfo.findOne({ $and: [{ version }, { language }] });
if (info) {
const update = await PageInfo.findOneAndUpdate({ version: { $eq: version } }, {
$set: {
version,
terms,
language
}
}, { new: true });
return res.status(200).json({ type: 'update', data: update });
}
info = await PageInfo.create({
version,
terms,
language,
});
return res.status(200).json({ type: 'new', data: info });
} catch (e) {
return res.sendStatus(500);
}
});
It looks like GridFS is what you will want to use.
You can read more about it here: GridFS
If this doesn't solve your issue, based on my experience, these kinds of issues arise when your schema is poorly modeled so you may want to reconsider how you model it.
Related
How can i display newest user post in my app? i have a backend route which display user post but i want that route display latest post of user So how can i do that in my code?
My code:
router.get('/postdata', async (req, res) => {
try {
// Find all users in the database
const users = await User.find();
// Map over the users array and return an array of objects
// with the same username, profile_image, and postImage
const userData = users.flatMap(user => {
return user.posts.map(post => ({
username: user.username,
profile_image: user.profilepic,
postImage: post.post,
}));
});
return res.json(userData);
} catch (err) {
return res.status(500).json({ error: err.message });
}
});
If your posts model has created_at or updated_at properties that keep track of when an image was uploaded, you could use that to sort the array in your map.
Let's say your userData array has similar output to this.
[
{
username: 'user1',
profile_image: 'https://your_domain.com/user1-profile.jpg',
postImage: 'https://your_domain.com/user1-post1.jpg',
created_at: '2023-01-01T11:00:00.000
},
{
username: 'user2',
profile_image: 'https://your_domain.com/user2-profile.jpg',
postImage: 'https://your_domain.com/user2-post1.jpg',
created_at: '2023-01-01T12:00:00.000
}
]
Then you can sort the array before rendering it.
const sorteduserData = userData.sort((a, b) => {
return new Date(b.created_at) - new Date(a.created_at);
});
It's a good practice to have your backend do the sort to reduce overhead on the front-end and to have your application load faster.
Many of headless CMSs have these features built in.
I am currently making a project using React TypeScript, MongoDB, and Express.js. I am trying to update the field value in my MongoDB document, and it is supposed to be a string, but instead it is automatically turning it into an object. Has anyone had that problem before? If so, how did you fix it?
How it's supposed to be:
character_name: "string"
How it's updating:
character_name: {
"string": ""
}
I've even logged it in the console to show me the type of data, and it's saying it's a string, so I don't know what it could be doing?
The backend routes:
routes.put("/change-name", async (req, res) => {
const name = req.body as string;
try {
const client = await getClient();
const result = await client.db().collection<Account>('accounts').updateOne({ username: "AndrewDamas" }, {$set: {character_name: name}});
if (result.modifiedCount === 0) {
res.status(404).json({ message: "Not Found" });
} else {
res.json(name);
}
} catch (err) {
console.error("FAIL", err);
res.status(500).json({ message: "Internal Server Error" });
}
});
The service code on the frontend side:
export function changeName(name: string){
return axios.put(`${baseUrl}/change-name`, name)
.then(res => res.data);
}
And how I used it in my code:
function saveData(){
console.log(ourCharacterName);
changeName(ourCharacterName);
}
Any help would be greatly appreciated! Thanks.
Put request. When sending data as body, it's going to arrive as json in your server . So you can either deconstruct it or use dot notation in your route method.
return axios.put(`${baseUrl}/change-name`, {name:name})
Deconstruct the variable from the body
const {name} = req.body;
Update the document
... {$set: {character_name: name}}
Problem
Every time you use as in TypeScript it means that something is wrong.
const name = req.body as string;
Your body isn't really a string, your body is the object:
{
"string": ""
}
Solution
const { string: name } = req.body;
I'm trying to save multiple documents in mongodb using mongoose; and I'm also willing to prevent duplicates. my function looks sth like this:
const Stock = require('./models/stock')
let _symbol = 'symb'
const writeToDB = async (dataObj) => {
try {
let stock = await Stock.find({symbol : _symbol } , function (err) {
if(err) return null
})
if (!stock) {
stock = new Stock({
dataObj
})
await stock.save()
console.log(`${symbol} is successfully saved to database`)
} else {
stock = await Stock.updateMany(
dataObj, function (err) {
if (err) {
console.log(err)
} else {
console.log(`${symbol} successfully added`)
}
})
}
} catch (error) {
console.log(error)
}
}
but I keep getting timeout error. can someone pls inform me what's wrong.
update
with a well handled connection approach findOneAndUpdate()works fine
Using the upsert option, in findOneAndUpdate(). An upsert behaves like a normal findOneAndUpdate() if it finds a document that matches filter. But, if no document matches filter, MongoDB will insert one by combining filter and update as shown below
var query = {symbol : _symbol };
try{
let result = await Stock.findOneAndUpdate(query, dataObj, {upsert: true})
}
catch(err){
console.log();
}
if you have a big collection, for increase speed findOneAndUpdate(), you should indexed symbol field.
when you use async await, it's better don't use callback and use try catch
I think the best, simply and easy way to prevent duplicate values is use unique value in the schema.
So your Stock schema has to have something similar to this:
symbol:{
type: String, // or whatever
unique: true
}
If you try to insert two object with same value, mongoose will trhow an error like:
MongoError: E11000 duplicate key error dup key: { : "repeatedSymbol" }
Also you can check the documentation.
I'm currently working on a project using Node/Express/MongoDB. I'm using Mongoose to create my schema's and interface with DB. I'm using "express-sessions" module and have a session value set. Specifically, "req.session.user" which equals the username when logged in.
My question here, is how do I go about inserting the session value into mongodb? I have my model defined properly.
doc_type.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TypesSchema = new Schema({
type_id: {
type: String,
uppercase: true,
required: true
},
type_description: {
type: String,
required: true
},
created_by: {
type: String,
required: false
},
creation_date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('document_types', TypesSchema);
admin.js with routes defined.
adminRouter.route('/doc_types')
.get((req, res) => {
Type.find({}, (err, types) => {
if (err) {
console.error(err)
res.json(err)
}
else if (!req.session.user || !req.session.badge) {
res.redirect('/login');
}
else if (req.session.user || req.session.badge) {
res.render('doc_types', { pageTitle: 'Document Types', types: types, currentUser: req.session.user })
}
})
})
.post((req, res) => {
var type = new Type();
type.type_id = req.body.input_type_id;
type.type_description = req.body.input_type_description;
type.created_by = req.session.user;
type.save((err) => {
if (err) {
console.error(err)
res.json(err)
}
else {
res.json("Success!");
}
})
});
If you look under the .post method, you'll notice the line "type.created_by = req.session.user;". I then save my data into my db via schema. Upon doing so, my session value isn't passed into mongoose scheme. It's empty. However, when I console.log the req.session value, it displays fine there.
Can someone clarify my issue here? I'm stumped. It's probably something stupid I've overlooked.
Welp, it was something stupid. :) I was using postman to "POST" my data to the page. Postman has no idea what the session value was, therefore, no data sent to the mongoose document id. The session was only stored on the server/browser side. Lesson learned, haha.
Using the MEAN stack, I'm attempting to have an admin account update another user's information, in this case, their title/role on the site. The problem I have is that the only function available when editing a user is the save() function. It might be that I can utilize the update function, and if that is the case please let me know, but it doesn't look possible:
The problem arises that when the user is saved, it creates a new document, and overwrites the user's password and salt to some value. I'd like to be able to call an "update" function that will only update the one field, but I can't figure out how to. Is there a way to do this with the save function?
Relevant Code:
exports.updateUserRoles = function(req, res) {
var currUser = req.body;
User.findById(currUser._id, function(err, user) {
//user.roles = currUser.roles;
user.save( { _id : '56467b28ba57d8d890242cfa', roles : 'admin' } );
//THE BELOW WAS A PREVIOUS ATTEMPT
/*user.save( function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(user);
console.log('test2');
}
});*/
});
};
Trying something else that seems very close, but still not quite there yet.
Here's what I'm running:
exports.updateUserRoles = function(req, res) {
var currUser = req.body;
User.findById(currUser._id, function(err, user) {
//user.roles = currUser.roles;
//user.roles.set(0, 'admin');
console.log('test');
user.update(
{ _id: '56467b28ba57d8d890242cfa' },
{
$set: {
roles: 'admin',
},
}
);
console.log('test2');
});
};
Upon hitting the user.update line, we have the user in the local variables, seen:
user.update goes into this Document.prototype.update function, seen:
The args look to be building right, which _id we are targeting and what the action is, seen:
But then after running, nothing seems to change. I'm very much stumped.
For updates various fields in mongodb you can use update with different atomic operators, like $set, $unset, $push etc.
Example:
var updateUserRoles = function(db, callback) {
db.collection('users').updateOne(
{ "_id", : "user_id", },
{ $set: { "password": "new_password" } },
function(err, results) {
console.log(results);
callback();
}
);
};