committeeHead is a reference in collection users. I want to populate this id to get the specific data.
tried using Promise.all but I don't completely understand it and it isn't working for me.
const getAllCommittees = async (req, res, next) => {
try {
const committees = await db.collection("committees").get();
const committeesArray = [];
committees.forEach((doc) => {
committeesArray.push({ id: doc.id, ...doc.data() });
});
const committeesWithUsers = await Promise.all(
committeesArray.map((committee) => {
const user = db.collection("users").doc(committee.committeeHead).get();
return {
committee,
user,
};
})
);
res.json(committeesWithUsers);
} catch (err) {
console.log(err);
next(err);
}
};
Related
I try to console.log the user as below showing for the further manipulation of it but the weird thing is the places properties somehow disappeared, and if you check on the database, it's still there.
Anyone, please tell me what's wrong ...
const { validationResult } = require('express-validator');
const HttpError = require('../models/http-error');
const getCoordsForAddress = require('../util/location');
const PlaceSchema = require('../models/place_schema');
const UserSchema = require('../models/user_schema');
const { default: mongoose } = require('mongoose');
const { findById } = require('../models/place_schema');
const getPlaceById = async (req, res, next) => {
const placeId = req.params.pid;
let place;
try {
place = await PlaceSchema.findById(placeId);
} catch (err) {
const error = new HttpError('Somthing wehnt wrong, could not find a place', 500);
return next(error);
};
if (!place) {
const error = new HttpError('Could not find a place for the provided id.', 404);
return next(error);
} else {
res.json({ place: place.toObject({ getters: true }) });
};
};
const getPlacesByUserId = async (req, res, next) => {
const userId = req.params.uid;
let places;
try {
places = await PlaceSchema.find({ creator: userId });
} catch (err) {
const error = new HttpError('Something went wrong, couldn nott find the place', 500);
return next(error);
};
if (!places || places.length === 0) {
return next(
new HttpError('Could not find a place for the provided user id.', 404)
);
};
res.json({ places: places.map(p => p.toObject({ getters: true })) });
};
const createPlace = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors);
return next(new HttpError('Invalid inputs passed, please check your data', 422));
};
const { title, description, address, creator, image } = req.body;
let coordinates;
try {
coordinates = await getCoordsForAddress(address);
} catch (error) {
return next(error);
}
const createdPlace = new PlaceSchema({
title,
description,
image,
location: coordinates,
address,
creator
});
// check if a exist userid is existing
let user;
try {
user = await UserSchema.findById(creator);
} catch (err) {
const error = new HttpError('Creating place failed, please try again.', 500)
return next(error);
};
if (!user) {
const error = new HttpError('Could not find user for provided id', 404)
return next(error);
}
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await createdPlace.save({ session: sess });
user.places.push(createdPlace);
await user.save({ session: sess });
await sess.commitTransaction();
} catch (err) {
const error = new HttpError('Creating place failed, please try again.', 500);
return next(error);
};
res.status(201).json({ place: createdPlace });
};
const updatePlace = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors);
return next(HttpError('Invalid inputs passed, please check your data', 422));
};
const { title, description } = req.body;
const placeId = req.params.pid;
try {
PlaceSchema.findByIdAndUpdate(placeId, {
title, description
})
} catch (err) {
const error = new HttpError('Somthing went wrong, could not update the place.', 500)
return next(error);
};
res.status(200).json({ place: updatedPlace.toObject({ getters: true }) });
};
const deletePlace = async (req, res, next) => {
const placeId = req.params.pid;
let thePlace;
let creator;
try {
thePlace = await PlaceSchema.findById(placeId);
creator = await UserSchema.findById(thePlace.creator);
} catch (err) {
const error = new HttpError('Somthing went wrong, could delete the place', 500);
return next(error);
};
console.log(creator);
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await PlaceSchema.findByIdAndDelete(placeId, { session: sess });
await creator.places.pull(creator);
await UserSchema.save({ session: sess });
await sess.commitTransaction();
} catch (err) {
// console.log(err)
const error = new HttpError('Somthing went wrong, could delete the place', 500);
return next(error);
};
res.status(200).json({ message: 'Deleted place.' });
};
exports.getPlaceById = getPlaceById;
exports.getPlacesByUserId = getPlacesByUserId;
exports.createPlace = createPlace;
exports.updatePlace = updatePlace;
exports.deletePlace = deletePlace;
When console.log the user, there is no places of an array showing
But it's actually in the database, somehow it disappears when console.log
I have an express app that looks like this.
const app = require('express')();
// Task model
const Task = require('./models/Task');
const { param, validationResult } = require('express-validator');
const getTaskValidations = [
param('id')
.custom(async (id, { req }) => {
try {
const task = await Task.findOne({ _id: id, user: req.user.id });
if (!task) Promise.reject('Task not found');
} catch (err) {
// Handle error
}
})
]
const validate = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(401).json({ message: errors.array()[0].msg });
}
next();
}
// Get Task by id
app.get('/tasks/:id', getTaskValidations, validate, async (req, res) => {
try {
const task = await Task.findById(req.params.id);
res.json(task)
} catch (err) {
// Handle err
}
})
I want to get the task by id. In GET tasks/:id the req.params.id will contain the id of the task.
The Task Model looks like this
{
id:
task:
user:
}
By looking at the endpoint it is clear that I'm passing two middlewares.
The first middleware getTaskValidations will check if the task will given id and req.user exists.
The second middleware validate will check for errors.
And then again will query database for task and send data to the client causing 2 database queries.
How can I reuse the same task obtained in the getTaskValidations middleware.
you can add result of query add to the req.body.task like this
const getTaskValidations = [
param('id')
.custom(async (id, { req }) => {
try {
const task = await Task.findOne({ _id: id, user: req.user.id });
req.body.task = task
if (!task) Promise.reject('Task not found');
} catch (err) {
// Handle error
}
})
]
in controller
app.get('/tasks/:id', getTaskValidations, validate, async (req, res) => {
try {
let {task} = req.body
res.json(task)
} catch (err) {
// Handle err
}
})
You can store the response you get from the query in the request(req).
const task = await Task.findOne({ _id: id, user: req.user.id });
if (task)
req.task = task;
else
Promise.reject('Task not found');
Later on, in the API endpoint, you can simply use
app.get('/tasks/:id', getTaskValidations, validate, async (req, res) => {
try {
const task = req.task;
res.json(task)
} catch (err) {
// Handle err
}
});
to get the task obtained in the getTaskValidations middleware.
I need help with GET function on Firebase.
This code is intended to fetch data from firestorage:
app.get("/", async (req, res) => {
const snapshot = await admin
.firestore()
.collection("articles")
.orderBy("createdate", "desc")
.get();
const articles = [];
snapshot.forEach((doc) => {
const data = doc.data();
articles.push({ id: doc.id, ...data });
});
res.status(200).send(JSON.stringify(articles));
});
but how can I render that data by the tags if I call it
app.get("/:tag", async (req, res) => {
My data looks like this
collection - articles
- id
- title
- body
- tags - [0]culture
- [1]technology
i find the solution with this code
app.get("/tag/:tag", async (req, res) => {
await admin
.firestore()
.collection("articles")
.where("tags", "array-contains", req.params.tag)
.get()
.then((snapshot) => {
const articles = [];
snapshot.forEach((doc) => {
const data = doc.data();
articles.push({ id: doc.id, ...data });
});
return res.status(200).send(JSON.stringify(articles));
})
.catch((error) => {
res.status(404);
});
});
i use .where("tags", "array-contains", req.params.tag)
I want to find an existing document in MongoDB by its _id. Everything works except trying to edit existing just creates a new document with a new _id instead of updating the current. It seems that it skips if (this._id) { in the model file. Very frustrated because I can see the issue but cannot find a fix. Thanks in advance!
plant.js controller:
exports.getEditPlant = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
console.log('Not Edit Mode');
}
const dbId = req.params._id;
Plant.findById(dbId)
.then(plant => {
if (!plant) {
console.log('Err');
res.redirect('back');
}
res.render('account/edit-plant', {
pageTitle: 'Edit Plant',
path: '/account',
plant: plant,
edit: editMode
});
}).catch(err => {
console.log(err);
});
};
exports.postEditPlant = (req, res, next) => {
const updatedName = req.body.common_name;
const scientific_name = req.body.scientific_name;
const updatedImg = req.body.image_url;
const slug = req.body.slug;
const updatedPlant = new Plant(updatedName, scientific_name, updatedImg, slug, new ObjectId(id));
updatedPlant.addMyPlant()
.then(plant => {
res.redirect('home');
}).catch(err => {
console.log(err);
})
};
plant.js model:
const mongodb = require('mongodb');
const getDB = require('../util/database').getDB;
module.exports = class Plant {
constructor(common_name, scientific_name, image_url, slug, id) {
this.common_name = common_name;
this.scientific_name = scientific_name;
this.image_url = image_url;
this.slug = slug;
this._id = id;
}
addMyPlant() {
const db = getDB();
let dbOp;
if (this._id) {
dbOp = db
.collection('myplants')
.updateOne({ _id: new mongodb.ObjectId(this._id) }, { $set: this });
} else {
dbOp = db.collection('myplants').insertOne(this);
}
return dbOp
.then(result => {
})
.catch(err => {
console.log(err);
});
}
static getMyPlants() {
const db = getDB();
return db.collection('myplants')
.find().toArray()
.then(plants => {
return plants;
}).catch(err => {
console.log(err);
});
}
static findById(dbId) {
const db = getDB();
return db
.collection('myplants')
.find({ _id: new mongodb.ObjectId(dbId) })
.next()
.then(plant => {
return plant;
})
.catch(err => {
console.log(err);
});
}
}
You need to assign the known _id to the ObjectID outside of the query.
In your code, you instantiate a new ObjectID inside your query but the value you passed in is not found.
This is a simplified version of your class with tests:
const mongodb = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
const url = "mongodb://localhost:27017/mydb";
class Plant {
constructor(name) {
this.name = name;
}
// this method pulls all the records for me to test results
getAll() {
mongodb.connect(url, { useUnifiedTopology: true }, (err, db) => {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("plants").find({}).toArray(function (err, result) {
if (err) console.log(err);
console.log(result);
db.close();
});
})
}
// update single record
updateMyPlant() {
mongodb.connect(url, { useUnifiedTopology: true }, (err, db) => {
if (err) console.log(err);
console.log("Mongo connected...");
const dbo = db.db("mydb");
// if you know the _id
// instantiate a variable outside your query
// now const id is the same as the _id you wants to query
const id = ObjectID("5fd8a1100617b03d8c737da0");
const myquery = { "_id": id };
const newvalues = { $set: { "name": "Marlon Brando" }};
try {
dbo.collection("plants").updateOne(myquery, newvalues, (err, res) => {
if (err) console.log(err);
console.log("update result", res.result, res.upsertedId);
db.close();
})
}
catch (e) {
console.log(e);
}
})
}
}
// test
const plant = new Plant("Alexa");
plant.updateMyPlant();
plant.getAll();
module.exports = Plant;
/**
* Logs:
* Mongo connected...
update result {
n: 1,
nModified: 1,
ok: 1
}
null
[{
_id: 5 fd8a1100617b03d8c737da0,
name: 'Marlon Mickey',
scientific_name: 'Brittain'
}]
*/
As you can see the _id is retained while the properties you want to change are updated.
See more info about ObjectID here
Cannot get the async / await functions to work properly in my card game app.
(a) I get the 201 response with no data.
(b) the deck document seems to be created afterwards, with the players field an empty array, indicating it is done after the deck is saved to the mongoDB
Below is my code. Any help is appreciated.
router.js
router.post('/game', (req, res, next) => {
try {
const { cards, playerNames, attributes } = req.body;
const newDeck = deck.start(cards, playerNames, attributes);
res.status(201).send(newDeck);
} catch (err) {
next(err);
};
});
/services/deck.js
exports.start = async (cards, playerNames, attributes) => {
try {
const users = await user.create(playerNames);
const deck = new Deck({
cards,
attributes,
players: users
});
return await deck.save((err, newDeck) => {
if (err) console.log(err);
console.log('RESULT', newDeck);
});
} catch (err) {
console.log(err);
}
};
/services/user.js
exports.create = async (users) => {
if (users.constructor === String) {
const user = new User({displayname: users});
return await user.save((err, newUser) => {
if (err) console.log(err);
console.log('NEW USERS ', user);
return newUser;
});
} else if (users.constructor === Array) {
let userList = [];
await users.forEach(name => {
const user = new User({displayname: name.toString()});
return user.save((err, newUser) => {
if (err) {
console.log(err);
} else {
userList.push(newUser);
return newUser;
}
});
});
console.log('NEW USERS ', userList);
return userList;
};
};
I am not familiar how you're handling promises,
but forEach is not promise-aware, that's how it has been designed, so it will not handle your asynchronous code properly
replace it with normal for loop or for-of loop, and add the await keyword in front of the user.save() method