I am trying to display a list of users but the logged-in user shouldn't see himself in the list. I can't make the request to get all users but current user to work.
router.get("/", auth, async (req, res) => {
try {
const users = await User.find({ user: { $ne: req.user.id } }).select([
"email",
"username",
"bio"
]);
res.json(users);
} catch (err) {
console.error(err.message);
res.status(500).send("Servor Error");
}
});
module.exports = router;
This request below gets the current user and it works.
router.get("/", auth, async (req, res) => {
try {
const user = await User.findOne({
user: req.user.id
});
if (!user) {
return res.status(400).json({ msg: "There is no profile for this user" });
}
res.json(user);
} catch (err) {
console.error(err.message);
res.status(500).send("Servor error");
}
});
module.exports = router;
You need to use _id field inside the query filter instead of user:
const users = await User.find({ _id: { $ne: req.user.id } }).select([
"email",
"username",
"bio"
]);
Related
I'm using mongoose and I would like that when I get all users send me uid instead of _id.
const allUssers = (req, res, next) => {
try {
User.find({})
.select("username")
.select("email")
.select("image")
.exec((err, users) => {
if (err) {
return res.status(400).json({
ok: false,
msg: "Error listing users",
});
}
return res.status(200).json({
ok: true,
users: users,
});
});
} catch (err) {
return res.status(500).json({
ok: false,
msg: "Please contact with administrator",
});
}
};
You can update your schema to use an alias:
let User = new Schema({
_id: { type: String, alias: "uid" }
});
Or you can map your users to something different:
return res.status(200).json({
ok: true,
users: users.map(({ _id, ...user }) => ({ uid: _id, ...user }),
});
I'm using this route to allow a user to change their email address. However, it currently lets them add an email address that is already used by another user. How can I prevent this (and send an alert in this situation). Also, I'm wondering if .findOneAndUpdate() is appropriate here as it may stop after finding the first one.
Thanks
app.post('/changeUserEmail', function (req, res) {
db.collection("userDB").findOneAndUpdate(
{username: req.user.username},
{ $set: {email: req.body.newEmail}},
{new: true},
(err, data) => {
if (err) {
console.log(err);
}
console.log(null, data);
}
)
res.render(process.cwd() + "/views/options", {
username: req.user.username,
email: req.body.newEmail,
alert: "Email changed"
});
});
You could first check if the email exists before you update something
app.post("/changeUserEmail", async function(req, res) {
let { username } = req.user;
let { newEmail } = req.body;
let emailExist = await db.collection("userDB").findOne({ email: newEmail });
if (emailExist)
return res.render(process.cwd() + "/views/options", {
alert: "Email already exists"
});
await db
.collection("userDB")
.findOneAndUpdate(
{ username },
{ $set: { email: newEmail } },
{ new: true }
);
res.render(process.cwd() + "/views/options", {
username,
email,
alert: "Email changed"
});
});
Hello everybody i have this bad code for me how i can optimize it ?
If i used SQL i can do used inner Queries in one query...
"User" it's only object from mongoose
getProfile: async (req, res) => {
const { id } = req.params;
try {
const {
image,
name,
gender,
about,
email,
phone,
address
} = await User.findById({ _id: id }).select('image name gender about email phone address');
const subscriptions = await Subscriber.countDocuments({ userId: id });
const subscribers = await Subscriber.countDocuments({ subscriberId: id });
const user = {
image,
name,
gender,
subscriptions,
subscribers,
about,
email,
phone,
address
};
res.json(user);
} catch (err) {
console.log(err);
}
}
PS.
I only study with this technologies
If i used spread operator of result of my query from User i have like this:
And that what i have in result
module.exports = {
getProfile: async (req, res) => {
const { id } = req.params;
try {
const [data, subscriptions, subscribers] = await Promise.all([
User.findById( { _id: id },
{
__v: false,
password: false,
date: false,
_id: false
},
),
Subscriber.countDocuments({ userId: id }),
Subscriber.countDocuments({ subscriberId: id })
])
const user = {
...data._doc,
subscriptions,
subscribers
}
res.json(user);
} catch (err) {
console.log(err);
}
}
Since all of your queries are independent, the best we can do is execute all of them parallelly with Promise.all(). Try something like this:
getProfile: async (req, res) => {
const { id = _id } = req.params;
try {
const getUser = User.findById({ _id }).select('image name gender about email phone address');
const getSubscriptions = Subscriber.countDocuments({ userId: id });
const getSubscriber = Subscriber.countDocuments({ subscriberId: id });
const [userData, subscriptions, subscribers] = await Promise.all([getUser, getSubscriptions, getSubscriber]);
const user = {
...userData,
subscriptions,
subscribers,
};
res.json(user);
} catch (err) {
console.log(err);
}
}
Hope this helps :)
You can embed subscriptions [array of documents] in the User model. But bear in mind that could put limitations on your api, if subscriptions might be accessed regardless of its user.
So I currently have two collections. One that is 'posts' and the other one that is 'users'
This is post:
_id
title
text
user
date
and this is users:
_id
username
email
password
I'm trying to use aggregate in the following way:
router.get('/:user_id', async (req, res) => {
try {
// const profile = await User.findById(req.params.user_id);
const profile = await User.agregate([
{
'$lookup': {
'from': 'posts',
'localField': '_id',
'foreignField': 'user',
'as': 'posts'
}
}
]);
// Verify profile exists
if (!profile) return res.status(400).json({ msg: 'Profile not found' });
res.json(profile);
} catch (err) {
console.error(err.message);
if (err.kind == 'ObjectId') {
return res.status(400).json({ msg: 'Profile not found' });
}
res.status(500).send('Server error');
}
});
Notice that the first profile constant is commented but that's the one I use to fetch the users data according to the _id(req.params.user_id) of X user.
Now what I would like to create is to display all of the posts created by X user by accessing to their profile, so I need to match the corresponding user, I need to pass the req.params.user_id.
This is the new code that I have which is not working:
router.get('/:user_id', async (req, res) => {
try {
// const profile = await User.findById(req.params.user_id);
const profile = await User.agregate([
{
'$lookup': {
'from': 'posts',
'localField': '_id',
'foreignField': 'user',
'as': 'posts'
}
}, {
$unwind: "$posts"
}, {
$match: {
"posts.user": req.params.user_id
}
}
]);
// Verify profile exists
if (!profile) return res.status(400).json({ msg: 'Profile not found' });
res.json(profile);
} catch (err) {
console.error(err.message);
if (err.kind == 'ObjectId') {
return res.status(400).json({ msg: 'Profile not found' });
}
res.status(500).send('Server error');
}
});
The error that is displayed in my console.log is 'user.aggregate is not a function'. Hopefully I could explain myself, thanks!.
I just want to add a new field(posts array) into the the users collection.
If anyone has come to the same requirement just as I did, here it is the solution after two days of researching and asking lol.
router.get('/:user_id', async (req, res) => {
try {
const userId = req.params.user_id;
const [profile, postsByUser] = await Promise.all([User.findById(userId, '-password'), Post.find({ user: userId }).populate('user', ['_id', 'username', 'avatar']).sort({ date: -1 })]);
// Verify profile exists
if (!profile) return res.status(400).json({ msg: 'Profile not found' });
// res.json(profile);
res.json({ ...profile.toJSON(), postsByUser });
} catch (err) {
console.error(err.message);
if (err.kind == 'ObjectId') {
return res.status(400).json({ msg: 'Profile not found' });
}
res.status(500).send('Server error');
}
});
Even nowadays that's a useful example. Except the typo:
const profile = await User.agregate([
should be
const profile = await User.aggregate([
I have an application where the user logs in using facebook account, saving the id, name and email. I'm using https://github.com/jaredhanson/passport-facebook
UserSchema.statics.findOrCreateFaceBookUser = function(profile, done) {
var User = this;
User.findOne({
'email': profile.emails[0].value
}, function(err, user) {
if (err) {
throw err;
}
if (user) {
user.facebook = {
id: profile.id,
email: profile.emails[0].value,
name: profile.displayName
};
user.save(function(err) {
if (err) {
return next(err);
} else {
// done(null, user);
}
});
done(null, user);
} else {
User.findOne({
'facebook.id': profile.id
}, function(err, user) {
if (err) {
throw err;
}
//if (err) return done(err);
if (user) {
done(null, user);
} else {
User.create({
firstName:profile.name.givenName,
lastName:profile.name.familyName,
email: profile.emails[0].value,
gender:profile.gender,
image:"http://graph.facebook.com/"+profile.id+"/picture?type=normal",
facebook: {
id: profile.id,
email: profile.emails[0].value,
name: profile.displayName
}
}, function(err, user) {
if (err) {
throw err;
}
done(null, user);
});
}
});
}
});
The problem is that I need to fetch facebook friends who are also using the application, but the "id" returned by facebook graph does not match what I'm persisting in the application.
https://graph.facebook.com/me/friends?fields=id,name&access_token=xpto
The "profile.id" received the passport-facebook is different from the facebook graph field "id"