NodeJS Mongoose update document - node.js

I'm trying to update or create a document in a MongoDB collection, using "mongoose" this way :
this.statsModel.findOne(
{product_id: requestData.ean},
).then((stats: mongoose.Schema) => {
const productId: string = requestData.ean;
// Update stats with the new scan...
const beforeStats: mongoose.Schema = stats;
const scan: any = {
coords: {
lat: requestData.lat,
lon: requestData.lon,
},
at: new Date(),
};
if (stats) {
stats.scans.push(scan);
stats.update();
} else {
const newStat = new this.statsModel();
newStat._id = requestData.ean;
newStat.product_id = requestData.ean;
newStat.scans = [scan];
newStat.purchases = [];
newStat.save();
}
When this code runs, no new element appears in the "scans" property if had a stats document.
The document is properly created if the stats document was not found.
I tried to change "update()" method to "save()" method, but, this way, i got a "Version error No matching document for the id..."
What i'm doing wrong ?
Regards...

Finally, update the type of the stats promised to Model instead of mongoose.Schema :
this.statsModel.findOne(
{product_id: requestData.ean},
).then((stats: Model<Stats>) => {
const productId: string = requestData.ean;
// Update stats with the new scan...
const beforeStats: mongoose.Schema = stats;
const scan: any = {
coords: {
lat: requestData.lat,
lon: requestData.lon,
},
at: new Date(),
};
if (stats) {
stats.scans.push(scan);
stats.save();
} else {
const newStat = new this.statsModel();
newStat._id = requestData.ean;
newStat.product_id = requestData.ean;
newStat.scans = [scan];
newStat.purchases = [];
newStat.save();
}
So the save() method properly works...
Thx

Related

I can't access 'title' on mongosh - getting undefine

//here is my schema
const mongoose = require ('mongoose');
const Schema = mongoose.Schema;
const ResortSchema = new Schema ({
title: String,
price: Number,
descriptor: String,
places: String,
location: String
});
var Resortdata = mongoose.model('holidayresorts', ResortSchema);
module.exports = Resortdata;
// index.js - where I tried to access 'places' and 'descriptors'
const sample = array => array[Math.floor(Math.random() * array.lenght)];
const seedDB = async () => {
await holidayresorts.deleteMany({});
for (i = 0; i < 5; i++){
const random5 = Math.floor(Math.random() * 5);
const Resort = new holidayresorts ({
location: `${cities[random5].city} , ${cities[random5].state}`,
title: `${sample(descriptor)} ${sample(places)}`
})
await Resort.save();
}
}
seedDB();
// what I am getting in on mongosh
{
_id: ObjectId("630cecf45a6457bfe74c0b9d"),
title: 'undefined undefined',
location: 'Owerri , Imo',
__v: 0
}
]
Please I need help, why am I getting 'undefined' for my title?
I think my Schema is correct
I can't really figure out what is wrong
I am thinking it is from my array
Please I need help
Have been stuck for days now
Help me

How do I add an entry in an array inside MongoDB

Below is my code to add an item to an array inside a mongoDB object. I am trying to add a review for my restaurant
The restaurant object looks like:
_id: ObjectID("61723c7378b6d3a5a02d908e")
name: "Hotel"
reviews: Array
reviews.js:
const mongoCollections = require('../config/mongoCollections');
const restaurants = mongoCollections.restaurants;
module.exports = {
async created (restaurantId, title, reviewer, rating, dateOfReview, review) {
const restaurantsCollection = await restaurants();
let newReview = {
restaurantId : restaurantId,
title : title,
reviewer : reviewer,
rating : rating,
dateOfReview : dateOfReview,
review : review
};
const insertInfo = await restaurantsCollection.updateOne( {_id : restaurantId},{$addToSet: {reviews: newReview}} )
if (insertInfo.insertedCount === 0) throw 'Could not add review';
},
index.js:
const restaurantsData = require('./restaurants');
const reviewsData = require('./reviews')
module.exports = {
restaurants: restaurantsData,
reviews: reviewsData
};
seed.js: // to call the function
const dbConnection = require('../config/mongoConnection');
const data = require('../data/');
const restaurants = data.restaurants;
const reviews = data.reviews;
const main = async () => {
await reviews.created("61723c7378b6d3a5a02d908e", "random", "sam", 4, "25/2/2002",
"amazing");
}
main();
I tried to use update instead of updateOne but it shows a deprecated warning

How to create and update referenced documents with mongoose?

I have this setup
var NotesSchema = new mongoose.Schema({
title: String,
category: [{ type: mongoose.ObjectId, ref: "Categories", default: [] }],
},{ timestamps: { createdAt: 'created_at' } });
var CategoriesSchema = new Schema({
name: {type: String, required: true}
})
var Notes = mongoose.model('Notes', NotesSchema);
var Cat = mongoose.model('Categories', CategoriesSchema);
If I want to create a new note and categories I do this
.get('/new', async (req, res) => {
var post1= {
title : "Post: books, thriller, crime and classics",
favorite : true,
categories:[ 'thriller', 'books']
}
try{
var note = post1.categories.map( (cat)=>{
var ca = new Cat({name: cat})
ca.save()
return ca._id
})
post1.category = note
const newNote = new Notes(post1);
const n = await newNote.save()
res.send(n)
} catch(error) {
console.error(error);
};
})
If I were to create a new note that has some new categories I'm stuck.
var post1= {
...
categories:[ 'thriller', 'books', 'classics']
}
'thriller' and 'books' already exist, but 'classics' doesn't.
I tried Cat.find({"name": {$in: post1.categories}}).exec() but I can't seem to look through that data.
All the example tutorials seem to just add one new entry at a time.
Inside your post1.categories.map callback you are creating the Cat documents and call save() on them but you do not await the returned promise. So Note is created before those promises are fulfilled and thus post1.category will be an empty array.
You can fix this by awaiting the save-promises of the categories:
const savePromises = post1.categories.map((cat) => {
const ca = new Cat({name: cat})
return ca.save();
})
const categoryIds = (await Promise.all(savePromises)).map(category => category._id);
post1.category = categoryIds;
// rest of your code

Add a deeply embedded document conditionally if unique field value

I have following model and schemas in mongoose :
const Doc = mongoose.model(
"Doc",
new mongoose.Schema({
name: String,
subDocs: [SubDoc],
})
);
const SubDoc = new mongoose.Schema({
name: String,
subSubDocs: [SubSubDoc],
});
const SubSubDoc = new mongoose.Schema({
name: String,
});
This code adds a uniquely named embedded SubDoc to the parent Doc. By "uniquely named" I mean it will not create a subdocument if another subdocument in the parent has the same value for "name":
const createUniqueSubDoc = (docId, name) => {
return db.Doc.findOneAndUpdate(
{ _id: docId, "subDocs.name": { $ne: name } },
{
$push: {
subDocs: {
name: name,
},
},
},
{ new: true, useFindAndModify: false }
);
};
const run = async (doc) => {
let doc = await db.Doc.create({name:"Main document"})
createUniqueSubDoc(doc._id, "sub document name");
};
run();
addToSet doesn't work with dates or id's so I'm $ne as suggested here.
But how do I add a uniquely named embedded SubSubDoc to the already embedded SubDoc's subSubDoc field? You can't query the embedded SubDoc with findOneAndUpdate because it's only a schema not a model like the Doc model.
using MongooseArray methods:
const createUniqueSubSubDoc = async function (docId, subDocId, subSubDoc) {
const doc = await db.Doc.findById(docId);
const subDoc = doc.subDocs.id(subDocId);
if (subDoc.subSubDocs.find((ssd) => ssd.name == subSubDoc.name))
return "oops! you already gave another SubSubDoc this name";
subDoc.subSubDocs.push(subSubDoc);
await doc.save();
return doc.subDocs.id(subDocId);
};
createSubSubDoc(
"5f56d9621222bbcc3bf4ee41", // the id for a Doc
"5f56d9631222bbcc3bf4ee42", // the id for a SubDoc of that Doc
{ name: "subSubDoc name" } // the object for the new SubSubDoc
);
git repo

Mongoose: $inc not working

I am not sure what the problem is, as I've read numerous examples.
Taken from what I was advised here in this StackOverFlow(Mongoose - Increment a value inside an array of objects), I changed the format of poll at ease to accommodate what was recommended.
So I was able to create a document format as so:
{
"_id": "584c4160b3b22e1bdad59bce",
"title": "Food",
"description": "test",
"labelOptions": {
"burger": 29,
"coffee": 44,
"pizza": 23
},
"date": "Dec 10, 2016",
"__v": 0
}
Here's what I have so far:
Poll Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const pollData = new Schema({
title: String,
description: String,
labelOptions: {},
date: String
})
module.exports = mongoose.model('PollData', pollData)
Using express and mongoose, here's what I have:
app.put('/polls/:id', function(req, res){
let id = req.params.id;
let labelOption = req.query.labelOption;
let query = `labelOptions.${labelOption}`
Poll.findByIdAndUpdate(
id,
{$inc: { query: 1 } },
function(err, document){
console.log(err)
console.log(document)
}
)
})
In my terminal, I see that console.log(document it receives the document I was looking for but it does not update the value at all.
Am I setting up the Model correctly? Or does Mongoose does not support template strings?
***update
This is snippet of how I am creating documents
let labelOptions = {}; <=== creating object literal to hold as placeholder
const title = req.body.title;
const description = req.body.description;
req.body.labelOptions.split(/,\s*/).map( prop =>{
labelOptions[prop] = 0 // set counter to default 0
})
const poll = new Poll({
title: title,
description: description,
labelOptions: labelOptions,
date: moment().format('MMM D, YYYY')
});
poll.save(function(err) {
if (err) { return next(err); }
res.json({ message : 'Poll added!'})
});
After doing some research across the internet, I found the reason why it wasnt working: You can't initialize objects with 'dynamic' keys.
Source: Mongoose update on a string variable not working?
By knowing that, it was just a simple solution to initialize an literal object as so:
let id = req.params.id;
let labelOption = req.query.labelOption;
let query = "labelOptions." + labelOption
let obj = {
[query] : 1
}
Poll.findByIdAndUpdate(
id,
{$inc: obj },
function(err, document){
console.log(err)
console.log(document)
}
)

Resources