How to set $inc in a mongoose model instance when using .save()? - javascript

This is my schema:
const Schema = mongoose.Schema;
const urlSchema = new Schema({
original_url: String,
short_url: Number
});
Then I do this:
let urlInstance = new Url({ original_url: url, { $inc: { 'short_url': 1 }} });
urlInstance.save((err, doc) => {
if (err) return console.error(err);
console.log("saved ", doc);
res.json(doc);
});
also tried it like this:
let urlInstance = new Url({ original_url: url });
urlInstance.save(({ $inc: { 'short_url': 1 }}), (err, doc) => {
if (err) return console.error(err);
console.log("saved ", doc);
res.json(doc);
});
I don't know how to pass the $inc bit in without it complaining about syntax. What am I doing wrong here? Tried different ways and even using mongoose-sequence but seems like $inc should be easier?

Related

Node Js: Remove string array element from mongoDB

I have a user schema as follows:
const UserSchema = new mongoose.Schema({
skills: [String]
});
module.exports = mongoose.model("User", UserSchema);
And a Fetch request to delete a skill as follows:
const deleteItem = async (id) => {
try {
await fetch(`http://localhost:5000/api/user/deleteskill`, {
method: "DELETE",
headers: { "Content-Type": "application/JSON", token: accessToken },
body: JSON.stringify({ userid: userid , skill:id}),
})
.then((res) => res.json())
.then((data) => {
console.log("USER SKILLS:", data.userskills);
});
} catch (err) {
console.log(err);
}
};
Server
const deleteSkill = async (req, res) => {
try {
const user = await User.findById(req.body.userid)
//user.skills.pull(req.body.skill);
// removeskill = user.skills.filter(function(item) {
// return item !== req.body.skill
// })
if (user.skills.includes(req.body.skill)) {
res.status(400).json("Item Still Exists");
} else {
res.status(200).json("Item Deleted");
}
} catch (error) {
res.status(500).send({ error: error.message });
}
};
the array is in the following structure
[
'skill1', 'java', 'skill5'
]
I have tried to remove the user skill from the array in several ways but I still get res.status(400).json("Item Still Exists");. What I'm doing wrong?
Use the findOneAndUpdate method to find a document with the user id and update it in one atomic operation:
const deleteSkill = async (req, res) => {
try {
let message = "Item Deleted";
let status = 200;
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{ $pull: { skills: req.body.skill } },
{ new: true }
)
if (user && user.skills.includes(req.body.skill)) {
message = "Item Still Exists";
status = 400;
} else if (!user) {
message = "User Not Found";
status = 404;
}
res.status(status).send({ message });
} catch (error) {
res.status(500).send({ error: error.message });
}
};
I believe you want to remove skills from the database then the following function could help you out.
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
var myquery = { userid: userid, skillid: skillid};
dbo.collection("skills").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
db.close();
});
});
You have a method of removing elements from arrays, if you want to remove the first one you could use array.shift (more on it here), but if you want to delete it completely from your database you could always, find it and then update it.
User.update({ _id: userid }, { $pull: { "skills": "[skill]" }})

Specifying a condition in payload sent in findByIdAndUpdate

Accounts model:
let accountsSchema = new mongoose.Schema({
posts:{
type: Array
}
});
const Post = mongoose.model("Account", postSchema);
controller in Posts microservice, which populates the posts array in the Accounts microservice:
let myAccountPosts = await axios.get(`${process.env.ACCOUNTS_MICROSERVICE_URL}/router/account/${userID}`)
.then((resp) => {
resp.data.message.map((account) =>{
account.posts.map((post) =>{
if(myUserPostID !== post._id){
//the following resets the entire posts array in the other microservice, consider resetting/deleting only that particular post
let deletePostFromAccountsMicroservice = axios.patch(`${process.env.ACCOUNTS_MICROSERVICE_URL}/router/account/update/${userID}`, {"posts.$[]": "abc"}, (err) =>{
if(err) return err;
});
}else{
console.log("no")
}
});
});
}).catch((err) =>{
console.log("err: ", err.message);
return err;
});
Now I need to be able to update a single object in the array and not override the whole array.
This is what the response looks like:
{
posts:[{_id:'6290ed85716a08d29dab3aa5'}, { _id: '1234ed85716a08d29b35342' } ]
}
In the following line of code:
let deletePostFromAccountsMicroservice = axios.patch(`${process.env.ACCOUNTS_MICROSERVICE_URL}/router/account/update/${userID}`, {"posts.$[]": "abc"}, (err) =>{
if(err) return err;
});
I want the posts.$[] to target only the
object that has an _id that matches this condition (myUserPostID !== post._id)
How do achieve that?

mongoose find json inside layers json

queueModel.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var queueSchema = Schema({
title: String,
description: String,
abc:{
a1: String,
b1: String,
c1: String
},
});
var Queue = mongoose.model('Queue', queueSchema);
module.exports = Queue;
api1.js
Queue.findOne({ title: "zzzz"} ).exec((err, data) => {
if (err) console.log(err)
else console.log(data)
});
result is data ...
api2.js (problem)
Queue.findOne({ title: "zzzz", abc:{a1: "aaaa"} } ).exec((err, data) => {
if (err) console.log(err)
else console.log(data)
});
Why is it null?
I want to use a1 condition.
Ask a Solution.
Do not modify the schema.
Try this:
Queue.findOne({ title: "zzzz", "abc.a1": "aaaa"} } ).exec((err, data) => {
if (err) console.log(err)
else console.log(data)
});
To filter on the abc you need to do abc.a1 as the field.

Use Rename collection in mongoose

I have a problem. I renamed my collection responses into old. It works really well but now I need to retrieve my data and my impediment is that I only used the model to retrieve my data from a collection. But now I need to retrieve my data from my renamed collection but I have no model and schema. I tried to create a schema and a model but it didn't work. It returns no elements.
Here is a part of the code :
app.get("/Play", function(req, res) {
var urlTempBox = 'http://localhost:3000/Play';
///////////////////////////////////////////////////////////
request(urlTempBox, function(error, response, body) {
if (error) {
throw (error);
} else {
var jobj = JSON.parse(response.body);
persistRS(jobj);
setTimeout(function() {
ResponseDatabase.find()
.populate('unitCode')
.exec(function(err, finalData) {
if (err) throw (err);
mongoose.connection.db.listCollections({
name: 'old'
})
.next(function(err, collinfo) {
if (err) throw (err);
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
} else {
console.log('fk');
res.send(finalData);
}
})
})
}, 5000);
}
});
Here is the part where it doesn't work: console.log(oldData) returns nothing. And I know that my data is in the database when I try to retrieve them.
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
}
Finally I found how to do maybe it will be usefull for someone
You just need in your schema to precise the name of your collection like this
( collection : 'old' )
var nameSchemaOldRS = new mongoose.Schema({
MainClass: String,
BookingClass: String,
carID: String,
unitCode:{type: String, ref: 'Map' ,required: [true,'No post id found']},
Deck:Number,
Orientation:String,
Position:String,
}, {
versionKey: false,
collection : 'old'
},);

Mongoose: Find, modify, save

I have a Mongoose User model:
var User = mongoose.model('Users',
mongoose.Schema({
username: 'string',
password: 'string',
rights: 'string'
})
);
I want to find one instance of the User model, modify it's properties, and save the changes. This is what I have tried (it's wrong!):
User.find({username: oldUsername}, function (err, user) {
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
What is the syntax to find, modify and save an instance of the User model?
The user parameter of your callback is an array with find. Use findOne instead of find when querying for a single instance.
User.findOne({username: oldUsername}, function (err, user) {
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
Why not use Model.update? After all you're not using the found user for anything else than to update it's properties:
User.update({username: oldUsername}, {
username: newUser.username,
password: newUser.password,
rights: newUser.rights
}, function(err, numberAffected, rawResponse) {
//handle it
})
findOne, modify fields & save
User.findOne({username: oldUsername})
.then(user => {
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.markModified('username');
user.markModified('password');
user.markModified('rights');
user.save(err => console.log(err));
});
OR findOneAndUpdate
User.findOneAndUpdate({username: oldUsername}, {$set: { username: newUser.username, user: newUser.password, user:newUser.rights;}}, {new: true}, (err, doc) => {
if (err) {
console.log("Something wrong when updating data!");
}
console.log(doc);
});
Also see updateOne
I wanted to add something very important. I use JohnnyHK method a lot but I noticed sometimes the changes didn't persist to the database. When I used .markModified it worked.
User.findOne({username: oldUsername}, function (err, user) {
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.markModified(username)
user.markModified(password)
user.markModified(rights)
user.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
tell mongoose about the change with doc.markModified('pathToYourDate') before saving.
If you want to use find, like I would for any validation you want to do on the client side.
find returns an ARRAY of objects
findOne returns only an object
Adding user = user[0] made the save method work for me.
Here is where you put it.
User.find({username: oldUsername}, function (err, user) {
user = user[0];
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
You could also write it a little more cleaner using updateOne & $set, plus async/await.
const updateUser = async (newUser) => {
try {
await User.updateOne({ username: oldUsername }, {
$set: {
username: newUser.username,
password: newUser.password,
rights: newUser.rights
}
})
} catch (err) {
console.log(err)
}
}
Since you don't need the resulting document, you can just use updateOne instead of findOneAndUpdate.
Here's a good discussion about the difference: MongoDB 3.2 - Use cases for updateOne over findOneAndUpdate

Categories

Resources