Mongoose FindOneAndUpdate not Updating when Pushing an Object to a Nested Array - javascript

When trying to push to a nested array it's not updating in my database with the following code:
const obj = {
key: key,
user: user,
description: description,
date: Date.now(),
guildId: guildId,
};
const guild = await this.GuildModel.findOneAndUpdate(
{ guildId: guildId },
{ $push: { 'guildData.commandLogs': obj } },
);
My schema:
const GuildSchema = {
guildId: { type: String },
guildData: {
commandLogs: [CommandLogsSchema],
},
Any idea why my database isn't updating?

I think you might have some typos in your model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const GuildSchema = new Schema({ guildId: { type: String },
guildData: {
commandLogs: [CommandLogsSchema], })
in your controller, the filter condition that you're passing is not clear, which guildId you are using? also when you call the guildData.commandLogs field to update it you are missing brackets
const filter = { guildId: heretheactualId };
const update = { { $push: { commandLogs: obj} }};
const guild = await this.GuildModel.findOneAndUpdate(
filter,
update,
);
this is not going to fix your problem because I don't know what kind of errors you're having or your database model but these tips can already help.

Related

save an array of objects to MongoDB with Mongoose on Javascript

I have this data (json):
var unique =
[
{"name":"John", "number":"4132321234"},
{"name":"Jack", "number":"451232421234"},
{"name":"Maddy", "number":"12314124"},
{"name":"Alex", "number":"213468316"}
]
What I want to do, is save this data to my mongoDB collection, with the following schema (using mongoose):
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const nameSchema = new Schema({
name: {
type: String,
required: true,
},
number: {
type: String,
required: true,
},
});
const Name_db = mongoose.model('Name_db', nameSchema)
module.exports = Name_db;
I wrote a loop, to attempt to do this:
for (var k = 1; k < unique.length; k++) {
var name_mongo = new Name_db({
name: unique[k].name,
number: unique[k].number,
},
)
console.log(unique[k].name)
} name_mongo.save()
.then(results => {
res.send(results)
})
.catch(err => {
console.log(err);})
This doesn't work because right now it is only sending data once to mongo DB, meaning only of the arrays is actually being sent over, instead of all 3 of them being sent to mongoDB.
Would appreciate any help, thank you for the time.
Name_db.insertMany(unique)
.then((result) => console.log("Inserted", result))
.catch((error) console.log(error));
or
const result = await Name_db.insertMany(unique); // remember to decorate the function async

Mongoose update update nested object inside an array

I'm trying to query and update an element in the rosters array ( roster.schedule.monday.start) & then update the value in this example.
monday.start these two keys need to be dynamic
I think the approach would be something like this
Find document by _id
find matching object in array by _id
update nested values
I have tried this below with no luck, could anybody assist in this problem
many thanks
// Mongoose query
exports.updateRoster = (req, res) => {
const editDay = req.body.day;
const value = req.body.valueOfEntry;
const userId = req.body.id;
const rosterId = req.body.rosterId;
const startPerieod = req.body.time;
let dynObj = {
["rosters.$.schedule.$." + editDay + ".$." + startPerieod]: value,
};
Carer.updateOne({ "rosters._id": rosterId }, { $set: dynObj }).exec(
(err, roster) => {
if (err) {
return res.status(400).json({
error: err,
});
}
res.json(roster);
}
);
};
// Schema
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const carersSchema = new mongoose.Schema({
rosters: [
{
schedule: {
monday: {
start: { type: String },
finish: { type: String },
notes: { type: String },
},
],
});
module.exports = mongoose.model("Carers", carersSchema);
Try using $set and array filters like in the link
Carer.findOneAndUpdate({_id: carerId},
{
"$set": {[`rosters.$[outer].schedule.${editDay}.${startPerieod}`]: value}
},
{
"arrayFilters": [{ "outer._id": roasterId }]
},
function(err, response) {
if(err) console.log(err)
console.log(response)
})

How to add mongoose transaction and create a document?

I want to add a mongoose transaction in the POST method. When creating the transaction it should be creating a document called stock. Can anybody help me figure out what should I do here? I have a node/express/mongoose app with the following:
GoodsRecivedNote controller
router.post('/', async (req, res) => {
const session = await mongoose.startSession()
try {
const _id = await getNextSequence('goodsReceivedNote')
req.body.id = _id
const goodsReceivedNote = new GoodsReceivedNote(req.body)
const stocks = new Stock(req.body)
await goodsReceivedNote.save()
//use mongoose transaction
//creates a loop(data get from the arry called cart in goodsrecivednote)
for (const item of data) {
//insert stock modal(orderNo, packingId, orderSize, poNumber)
item.create({})
//insert(data, {session})
}
await session.commitTransaction()
res.sendStatus(200)
} catch (error) {
await session.abortTransaction()
return res.sendStatus(500)
} finally {
session.endSession()
}
})
GoodsRecivedNote model
const goodsReceivedNoteSchema = new Schema(
{
id: Number,
poNumber: String,
orderedDate: String,
supplier: String,
orderNo: String,
cart: [
{
packingId: Number,
actualSize: String,
orderSize: String,
brandId: Number,
artWork: String,
receivedQty: Number,
grnDate: String,
},
],
},
)
module.exports = mongoose.model(
'GoodsReceivedNote',
goodsReceivedNoteSchema
)
Stock model
const stockSchema = new Schema(
{
id: Number,
poNumber: Number,
orderNo: String,
packingId: Number,
orderSize: String,
receivedQty: Number,
availableQty: Number,
},
)
module.exports = mongoose.model(
'Stock',
stockSchema
)
Maybe you can try something like this
const session = await mongoose.startSession()
session.startTransaction()
const opts = { session }
const stocks = await new Stock(req.body).save(opts)
await goodsReceivedNote.save(opts)
...the rest of your code
When ever you call Save Update or Delete please add opts as option
Answer by 21bn gets the work done but withTransaction() is way better than startTransaction().
I recommend you use withTransaction instead.
const session = await mongoose.startSession();
await session.withTransaction(async (session) => {
// For create..
collection.create({something:"something"},{session:session});
});
For insertmany, updatemany, the rule is basically the same..
collection.updateMany({find_something:"something"},{name:"Some name"},{session:session});
If you want to find a document using session..
collection.findOne({_id: "some_id"}).session(session));

How can I loop through this array inside this instance of my mongoose model?

const postSchema = new mongoose.Schema({
post:[
{postId: String},
{commentComponent: [
{comment: [String]},
]}
]
})
const Posts = mongoose.model('Posts', postSchema)
This is the definition of the schema for modeling the mongodb
const postLinks = await getPostLinks();
const posts = new Posts({
for (let i = 0; i < postLinks.length; i++) {
const comment = await getComment(postLinks[i]) // here it takes postLinks as a paramaeter to get an array of comment
post: [
{postId: postLinks[i]},
{commentComponent: [
{comment: comment}
]}
]
}
})
const result = await posts.save()
is there a way of iterating inside this instance because the for loop here is not working
You need to pass an object to the Posts constructor with a property called post (which probably should be called posts, but will keep the original name below), and for this property, you need to specify an array.
This array can be built by using Array.prototype.map and Promise.all:
const post = await Promise.all(
postLinks.map(async (postLink) => {
const comment = await getComment(postLink);
return {
postId: postLink,
commentComponent: [{ comment }],
};
})
);
const posts = new Posts({ post });
const result = await posts.save();
But if you prefer, you can use the traditional for-loop (more similar to what you were trying to do) as well:
const post = [];
for (let i = 0; i < postLinks.length; i++) {
const comment = await getComment(postLinks[i]);
post.push({
postId: postLinks[i]},
commentComponent: [{ comment }]
});
}
const posts = new Posts({ post });
const result = await posts.save();
Based on your code example I am not certain what you are attempting to do. When using a Model and trying to create you can think of as a new singular record. If you are trying to insert many links into a single record I would suggest comma separating them then inserting that into your MongoDB.
But you cannot iterate inside your Posts class like that.
If I were you I would set up my file something like this:
file: models/Post.js:
const mongoose = require('mongoose');
const PostSchema = new mongoose.Schema({
text: {
type: String,
trim: true,
required: [true, 'Please add some text']
},
link: {
type: String,
required: [true, 'Please add link']
},
createdAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('Post', PostSchema);
Then create a controller js file
file: controllers/posts.js:
const Post = require('../models/Post');
// #desc Add Post
// #route POST /api/v1/posts
// #access Public
exports.addPost = async (req, res, next) => {
try {
// get post data from the request
// mongo returns a promise so await on it
const post = await Post.create(req.body);
return res.status(201).json({
success: true,
data: post
});
} catch (err) {
if(err.name === 'ValidationError') {
const messages = Object.values(err.errors).map(val => val.message);
return res.status(400).json({
success: false,
error: messages
});
} else {
return res.status(500).json({
success: false,
error: 'Server Error'
});
}
}
}
then in your router file, you can use your controller:
routes/post.js
const express = require('express');
const router = express.Router();
const { addPost } = require('../controllers/posts');
router
.route('/')
.post(addPost);
module.exports = router;

Why is this mongoose 'findOne' query always returning null?

I am trying to find a specific document with mongoose in my Cosmosdb with this query described below.
const mongoose = require('mongoose');
var ObjectID = require('mongodb').ObjectID
const keys = require('../config/keys');
const Item = mongoose.model('items');
const uploadToBlob = async (containerName, blobName, json, id) => {
console.log('id', id)
Item.findOne({ _id: id }, (foundItem) => {
console.log(foundItem)
});
console.log('here')
Item.findOneAndDelete({ name: blobName });
};
I am successfully able to find the document when querying like this below.
const scanMongo = () => {
Item.find({
_id: {
$gt: ObjectID.createFromTime(Date.now() / keys.mongoPurgeInterval)
}}, (err, foundItems) => {
if(err) {
console.log("Oops", err);
return;
}
foundItems.forEach(item => {
JSON.stringify(item)
const blobName = item.name;
json = "'"+item+"'"
const id = item._id
uploadToBlob(keys.containerName, blobName, json, id);
});
});
}
This is what the object I'm looking for looks like when pulled from the query above.
[ { _id: 5cabd5c6e16288230cba2cf6, name: 'test', value: 1, __v: 0 } ]
For kicks, here my model.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const itemSchema = new Schema({
name: String,
value: Number,
});
mongoose.model('items', itemSchema);
I'm befuddled. Any help would be bawler. Thanks!!!
Yeah, the first parameter is supposed to catch the error.
Item.findOne({ _id: id }, (error, foundItem) => {
console.log(foundItem)

Categories

Resources