How to return the a formatted response from a mongo query/projection? - mongodb

I'm trying to create an API to validate a promocode. I have minimal experience with mongo and the backend in general so I'm a bit confused in what is the best approach to do what I'm trying to accomplish.
I have this PromoCode form in the client. When a user types a promocode I would like for my backend to
verify if the code exists in one of the docs.
if it exists then return that code, the value for that code and the couponId
if the code doesn't exist then return an error.
My db is structured like this. The user will type one of those codes inside the codes: []
{
"_id": {
"$oid": "603f7a3b52e0233dd23bef79"
},
"couponId": "rate50",
"value": 50,
"codes": ["K3D01XJ50", "2PACYFN50", "COKRHEQ50"]
},
{
"_id": {
"$oid": "603f799d52e0233dd23bef78"
},
"couponId": "rate100",
"value": 100,
"codes": ["rdJ2ZMF100", "GKAAYLP100", "B9QZILN100"]
}
My route is structure like this:
router.post('/promoCode', (req, res, next) => {
const { promoCode } = req.body;
console.log('this is the req.body.promoCode on /promoCode', promoCode)
if (!promoCode) {
throw new Error('A promoCode needs to be passed')
}
promoCodesModel
.validatePromoCode(req.body.promoCode)
.then((response) => {
console.log('response inside /promoCode', response)
res.status(200).json({ data: response })
})
.catch((error) => {
res.status(400).json({ result: 'nok', error: error })
})
})
The validatePromoCode function is the following:
const validatePromoCode = async (code) => {
try {
let promoCode = await PromoCodesModel.find(
{"codes": code},
{_id: 0, codes: { $elemMatch: { $eq: code }} })
console.log('This is the promocode', promoCode)
return promoCode
} catch (err) {
throw new Error (err.stack)
}
}
All this seems to sort of work since I get the following response when the code is typed correctly
{
"data": [
{
"codes": [
"COKRHEQ50"
]
}
]
}
when typed incorrectly I get
{
"data": []
}
What I would like to get back is. (How can I accomplish this ?). Thanks
// when typed correctly
{
"data": { value: 50, couponId: "rate50", code: "COKRHEQ50" }
}
// when typed incorrectly
{
"error": "this is not valid code"
}
TL;DR: I would like to return a formatted query with specific values from a mongo query or an error object if that value does not exist on the document object.

Ok just figured it out
To be able to get the this responsed (what I wanted):
{
"data": [
{
"codes": [
"K3D01XJ50"
],
"couponId": "rate50",
"value": 50
}
]
}
I ended up having to do this on validatePromoCode
onst validatePromoCode = async (code) => {
try {
let promoCode = await PromoCodesModel.find(
{ codes: code },
{ _id: 0, codes: { $elemMatch: { $eq: code } }, couponId: 1, value: 1 },
)
return promoCode
} catch (err) {
throw new Error(err.stack)
}
}
But is there a better way on doing this ? Thanks

Related

How to populate array of objects in mongoose

I have this code -
const getAllCourses = async (req, res) => {
const courses = await Course.find({});
try {
await courses.populate('professor')
res.send({ status: 200, data: { courses } });
} catch (err) {
res.status(500).send({ status: 500, message: "Internal server error." });
}
};
Also, this is the response I'm getting from postman -
{
"status": 200,
"data": {
"courses": [
{
"_id": "61dc47f58f88c1a7e9bd36b6",
"name": "Course1",
"professor": "61dc1299431cd669faad7d0f",
"students": [
{
"student": "61dc0b7f103b531f105e8e4c",
"_id": "61dc47f58f88c1a7e9bd36b7"
},
{
"student": "61dc220885886a9f1d8e94d0",
"_id": "61dc47f58f88c1a7e9bd36b8"
}
],
"createdAt": "2022-01-10T14:51:33.313Z",
"updatedAt": "2022-01-10T14:51:33.313Z",
"__v": 0
},
{
"_id": "61dc47fb8f88c1a7e9bd36bf",
"name": "Course2",
"professor": "61dc1299431cd669faad7d0f",
"students": [
{
"student": "61dc0b7f103b531f105e8e4c",
"_id": "61dc47fb8f88c1a7e9bd36c0"
},
{
"student": "61dc220885886a9f1d8e94d0",
"_id": "61dc47fb8f88c1a7e9bd36c1"
}
],
"createdAt": "2022-01-10T14:51:39.704Z",
"updatedAt": "2022-01-10T14:51:39.704Z",
"__v": 0
}
]
}
}
Now what I'm trying to do is to populate the professor and the students but it doesn't seem to work.
I tried populating "courses.professor", "course.professor", "professor" but nothing worked for me.
What am I missing?
Here is an example of how this can be done for a document with an array friends on it:
User.
findOne({ name: 'Val' }).
populate({
path: 'friends',
// Get friends of friends - populate the 'friends' array for every friend
populate: { path: 'friends' }
});
I just solved it by chaining the populate method directly after the Course.find({}) and it just worked, I'm not sure why though.
Solution:
const getAllCourses = async (req, res) => {
const courses = await Course.find({}).populate('professor').populate('students.student');
try {
res.send({ status: 200, data: { courses } });
} catch (err) {
res.status(500).send({ status: 500, message: err.message });
}
};

mongoDB autcomplete returns empty array

I am using mongodb's sample movie database (https://docs.atlas.mongodb.com/sample-data/sample-mflix#std-label-sample-mflix) to experiment with mongodb's autocomplete functionality. The search always returns an empty array. I have set up a Search Index as follows:
{
"mappings": {
"dynamic": false,
"fields": {
"title": [
{
"minGrams": 3,
"tokenization": "edgeGram",
"type": "autocomplete"
}
]
}
}
}
The model and the search query are setup as follows:
// Creating the Movies model
const Movies = mongoose.model("Movies", new mongoose.Schema({}), "movies");
// Impplementing autocomplete search
app.get("/search", async (req, res) => {
try {
let result = await Movies.aggregate([
{
$search: {
autocomplete: {
path: "title",
query: req.query.title,
fuzzy: {
maxEdits: 2,
prefixLength: 3,
},
},
},
},
]);
res.status(200).json({
status: "success",
results: result.length,
data: { result },
});
} catch (error) {
console.log(error);
}
});
I am using postman to run test queries and a sample query is: 127.0.0.1:3030/search?title=black
The model can be queried using .find(), for example, and returns the full collection of documents.
Any and all help is greatly appreciated.

Update single specific field only when using $ in embedded document Mongodb

Here's my snippet of code.
router.post(
"/chapter/officers/edit/:id/:c_id",
async (req, res) => {
try {
const updateChapter = await Council.findOneAndUpdate(
{ "chapters._id": req.params.c_id },
{
"chapters.$.officers": req.body,
}
);
if (!updateChapter) return res.status(404).json({ msg: "Not found" });
res.json("Edit Success");
} catch (error) {
res.status(500).json({ msg: error.message });
}
}
);
I am planning on updating only one specific field at a time BUT when I tried to send this JSON from Postman
{
"grandTriskelion": "sample"
}
The other filled in field values becomes an empty string. Heres an example of my res.json
"_id": "5fc9cbb7ba7e2e2430c9a4d8",
"name": "Maria Aurora",
"code": "MA",
"chapters": [
{
"officers": {
"grandTriskelion": "sample",
"deputyGrandTriskelion": "",
"masterWilderOfTheWhip": ""
},
"_id": "5fca014e49fa3f2910794bb8",
"name": "Maria Aurora Community Based"
}
],
I've hit a roadblock. I'm a beginner at MERN stack.

Getting a $set error even though i am setting it?

chats.post('/approveUser', (req, res) => {
// let regex = new RegExp(req.body.requestId)
Chat.updateOne(
{ 'requests._id': req.body.requestId },
{ $set: {'approved': true} },
{ upsert: true }
)
.then(res => {
console.log('hi')
if (!res) {
res.status(404).send()
} else {
res.status(200).send(res)
}
})
.catch(err => {
console.log(err)
res.status(500).send(err)
})
})
Does anyone see why i'm getting an error? It says:
errmsg: '\'$set\' is empty. You must specify a field like so: {$set: {<field>: ...}}'
req.body.requestId is not undefined. This is the layout of each mongoDB document:
{
"_id":"5cd1f4aceb05c12298779345",
"title":"test 3",
"participants":[
{
"_id":"5cd1f4aceb05c12298779347",
"userEmail":"test#gmail.com"
},
{
"_id":"5cd1f4aceb05c12298779346",
"userEmail":"adam2.cole#northumbria.ac.uk"
}],
"chatType":"publicGroup",
"messages":[
{
"_id":"5cd254b591a0eb1de4a0863c",
"text":"hi",
"from":"test#gmail.com",
"dateTimeSent":"2019-05-08T04:01:57.732Z"
},
{
"_id":"5cd254b591a0eb1de4a0863b",
"text":"hi",
"from":"test#gmail.com",
"dateTimeSent":"2019-05-08T04:01:57.764Z"
}
],
"__v":0,
"requests":[
{
"approved":false,
"_id":"5cd2467891a0eb1de4a08631",
"userEmail":"test2#gmail.com"
}
]
}
The intention is to turn approved of any request to true. I'm failing to see why it won't work. Does anyone else see why?
Thanks.

how to write findOneAndUpdate query in express.js?

i have shown my data , which is stored in database like this
{
"_id": {
"$oid": "5799995943d643600fabd6b7"
},
"Username": "xx",
"Email": "xx#gmail.com",
"Info": "Deactivate",
"Description": "aajdjdjddjdkjddjdjdhdj",
"VerificationCode": "594565",
"VerificationExpires": {
"$date": "2016-10-07T10:20:20.077Z"
}
}
My controller:
if Username, Email, Info are matched I need to update " Info = 'Active' " this is working at the same time i need to delete 'VerificationCode' field and 'VerificationExpires' field how can i achieve this?
exports.updatearticle = function(req, res) {
Article.findOneAndUpdate(
{ "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" },
{ "$set": { "Info": "Active" } },
{ "new": true }
function (err, doc) {
if (err) { // err: any errors that occurred
console.log(err);
} else { // doc: the document before updates are applied if `new: false`
console.log(doc); // , the document returned after updates if `new true`
console.log(doc.Info);
}
}
);
};
above condtion matched and info getting changed but i want to delete VerificationCode,VerificationExpires some one help me out
exports.updatearticle = function(req, res) {
Article.findOne( { "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" }, function(err, result){
if (!err && result) {
result.Info = "Active"; // update ur values goes here
result.VerificationCode = "";
result.VerificationExpires = {};
var article = new Article(result);
article.save(function(err, result2){
if(!err) {
res.send(result2);
} else res.send(err);
})
} else res.send(err);
});
}
home this may help