Mongoose - find matching array values - node.js

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();

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.

Query MongoDB with mongoose and return an array of string matching one of the keys of the schema

I have the following schema and would love to query my database for all products for example where the seller matches foo, and return only the categories in a string array. how do I achieve this using mongoose?
seller: {
type: String
},
category: {
type: String
},
price: {
type: String
},
}, {
timestamps: true
});
const Product = mongoose.model("Product", productsSchema);```
so I tested a few methods and I found this to work very well;
app.get("/shop", (req, res) => {
console.log(req.params.roomID);
Product.find({room: req.params.roomID}, (error, doc) => {
const categoryArray = doc.map(newArray => newArray.category);
You can use findOne function in the following form
const stringArray = await Product.find({seller:'foo'},{category:1});

Update MongoDB document with PUT from Node.js API

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!

Resources