Update MongoDB document with PUT from Node.js API - node.js

I have a REST API written in Node.js using Mongoose to access the backend MongoDB database. I'm trying to change the value of a field in a document based on an ID field in document.
When using Postman to test the following code, I get an error: Cannot PUT /v1/remove/00001
//Cancel variation by ID
app.put('v1/remove/:id', async (request, response) => {
try {
var result = await variationsModel.findOneAndUpdate({ 'variationID': request.params.id }, {$set: { 'variationStatus': 'Cancelled'}}, { upsert: true, new: true });
response.send(result);
} catch (error) {
response.status(500).send(error);
}
})
This is the DB model defined for the API...
const variationsModel = mongoose.model("variations", {
"variationID": String,
"custID": String,
"projID": String,
"variationTitle": String,
"variationDesc": String,
"variationStatus": String,
"variationChargeable": String,
"variationCost": String,
"requireMaterial": String,
"variationRequestor": String,
"variationCreationDate": String,
"variationImages": [
{
"imageId": String
}
],
"variationCategory": String
});
Can anyone please help?
Thanks!

Related

Updating values in an object inside an array with Mongoose

I have a schema nested inside another(main) schema. I'd like to increase a Number field in the first schema, however it is an array. So I'd need to access that specific object in that array, and increase a field inside it which is a number. I think what I am looking for is the $inc operator, however I couldn't seem to get it to work.
My schema's:
const chainSchema = new mongoose.Schema({
chainName: String,
streak: Number,
});
const userSchema = new mongoose.Schema({
email: String,
password: String,
googleId: String,
pomodoroStreak: Number,
chains: [chainSchema],
});
Post route:
app.post("/chainDisplay", function (req, res) {
const clickedChain = req.body.secret;
const clickedButton = req.body.submit;
if (clickedButton === "increase") {
Chain.findOneAndUpdate(
{ chainName: clickedChain },
{ $inc: { streak: 1 } },
function (err, foundChain) {
if (!err) {
res.redirect("/chain");
}
}
);
} else if (clickedButton === "decrease") {
Chain.findOneAndUpdate(
{ chainName: clickedChain },
{ $inc: { streak: -1 } },
function (err, foundChain) {
if (!err) {
res.redirect("/chain");
}
}
);
}
});
I obtain the chainName and trying to use that as a parameter to find that specific object, and increase or decrease the streak by 1. Thank you for your help in advance.
I've tried using the $inc operator alongside mongoose's findOneandUpdate method. I am wondering if I should be updating the User, rather than the Chain itself. I was expecting to increase or decrease the "streak" key by 1 when the relevant button is clicked.

NodeJs: how to assign additional objects to mongoose query response JSON

Using mongoose I am querying a list of posts and would like to determine whether or not the user has liked the image or not within the query function by adding a boolean to the response JSON. I am trying to do this in a for loop.
However, when I console.log(), the post with the field returns correctly but does not amend it to the JSON.
My function:
function(req, res) {
var isLiked, likeCount;
Post
.find(/* Params */)
.then(posts => {
for (var index in posts) {
posts[index].isLiked = posts[index].likes.includes(req.headers.userid)
console.log(posts[index]) // does not show 'isLiked' field in JSON
console.log(posts[index].isLiked) // response is correct
}
res.send(posts) // does not have 'isLiked field
})
},
Post schema:
var postSchema = new Schema({
userId: {
type: String,
required: true
},
caption: {
type: String,
required: false
},
likes: [{
type: String,
}]
});
To add properties to queries objects you should convert them to JS objects:
function getPosts(req, res) {
Post.find(/* Params */).then((posts) => {
const result = [];
for (const post of posts) {
const postObj = post.toObject();
postObj.isLiked = postObj.likes.includes(req.headers.userid);
result.push(postObj)
}
res.send(result);
});
}
Cuz
Post.find()
is not return an object, you can set prop isLiked to posts[index] but it's private.
Easy way to fix it is use lean() method to get return object
Post.find().lean()
.then(//do what you want)

Update document in MongoDB via NodeJS

So my knowledge of NodeJS and MongoDD are non-existent (just need to do a small code update for a friend) and I'm stuck.
Need to update a single document inside a collection via a unique id but can't seem to do it.
Here's the Model (I've trimmed it down and cut out all unnecessary data). I'm trying to update the field notes inside a transaction.
In short each entry in the given (an Agent) table will have a collection of multiple Transactions & Documents. I need to update a specific Transaction with the unique _id that is auto generated.
import { Schema, model } from 'mongoose';
interface Transaction {
first_name: string;
last_name: string;
type: string;
notes: string;
}
interface Agent {
org_id: number;
transactions: Array<Transaction>;
documents: Array<string>;
}
const transactionSchema = new Schema<Transaction>({
first_name: { type: String },
last_name: { type: String },
type: { type: String },
notes: String,
});
const transactionsSchema = new Schema<Agent>({
org_id: { type: Number },
transactions: [transactionSchema],
documents: [documentTypesSchema],
});
const AgentTransaction = model<Agent>(
'agent_transaction_table',
transactionsSchema
);
export default AgentTransaction;
Here's what I tried but didn't work (obviously), again I've trimmed out all unnecessary data. Just to clarify, the endpoint itself works, but the DB update does not.
import AgentTransaction from '../models/transaction'; // the above model
transaction.put('/notes', async (req, res) => {
const { org_id, transaction_id, notes } = req.body;
try {
const notesResult = await AgentTransaction.updateOne({
'transactions._id': transaction_id,
}, {
$set: {
'notes': notes
},
});
res
.status(200)
.json({ message: 'Updated', success: true, notesResult });
} catch (error) {
res.status(400).send(error);
}
});
So I figured it out. Maybe it'll help someone else as well.
const notesResult = await AgentTransaction.updateOne({
'transactions._id': { $in: [trunc2] },
}, {
$set: {
'transactions.$.notes': notes
},
});
The main issue was that the payload object needed to target the collection folder + the wildcard + the field, not just only the field.

Unable to find index for $geoNear query error with mongoose

I have the following codes which try to create secondary indexes with mongoose. I have followed the mongoose official document to implement it ( mongoose documentation: Indexes section). However, when I send a GET request through Postman, an error, "unable to find index for $geoNear query", occurs. My understanding is that in my case, location is equivalent to a $geoNear object, so my code should be fine (I know it's not fine. That's why I have got an error). Any comments or suggestions would be greatly appreciated.
app.js(get endpoint)
app.get('/api/stores', (req, res) => {
const zipCode = req.query.zip_code;
const googleMapsURL = "https://maps.googleapis.com/maps/api/geocode/json";
axios.get(googleMapsURL, {
params: {
address: zipCode,
key : "KEY"
}
}).then((response) => {
const data = response.data
const coordinates = [
data.results[0].geometry.location.lng,
data.results[0].geometry.location.lat,
]
Store.find({
location: {
$near: {
$maxDistance: 3218,
$geometry: {
type: "Point",
coordinates: coordinates
}
}
}
}, (err, stores)=> {
if (err) {
console.log(err);
res.status(500).send(err);
} else {
res.status(200).send(stores);
}
})
}).catch((error)=> {
console.log(error);
})
})
store.js
const mongoose = require('mongoose');
const storeSchema = mongoose.Schema({
storeName: String,
phoneNumber: String,
address: {},
openStatusText: String,
addressLines: Array,
location: {
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
}
})
storeSchema.index({ location : "2dsphere"}, {sparse: true});
module.exports = mongoose.model('Store', storeSchema);
When creating a new index in MongoDB, you may have to drop the table as to have the index apply properly. Try creating the index on a fresh table. Does that work?
I figured out this error by first creating a new database and collection(I was using the default database named <dbname>). When I sent a POST request with the data I would like to store in MongoDB, MongoError: Can't extract geo keys appeared. I fixed this error by following this thread(reference). After these steps, my GET request worked and indexes were successfully created.

Mongoose - find matching array values

I'm creating a REST API with Node.js using Mongoose to access my backend MongoDB database. I have an array (variations) inside of one of my collections (also variations) and need to retrieve the object in the array that matches a provided value.
So far I've got this which returns an empty value...
//Get variation by ID
app.get('/v1/:id', async (request, response) => {
try {
var result = await variationsModel.find({ 'variationID': request.params.id }).exec();
response.send(result);
} catch (error) {
response.status(500).send(error);
}
})
And here's the model I've defined in the API...
const variationsModel = mongoose.model("variations", {
"variations": [
{
"variationID": String,
"custID": String,
"projID": String,
"variationTitle": String,
"variationDesc": String,
"variationStatus": String,
"variationChargeable": String,
"variationCost": String,
"requireMaterial": String,
"variationRequestor": String,
"variationCreationDate": String,
"variationImages": [
{
"imageId": String
}
],
"variationCategory": String
}
]
});
Anyone point me in the right direction?
Thanks!
The query should be
variationsModel.find({ 'variations.variationID': request.params.id }).exec();

Resources