MongoDB UpdateMany Method - node.js

how can i use the update Many Method inside my code?. Right now this code will insert the data over and over inside the table, i need to make it so it will update the old data and add new data if new data is available in the third party api. I'm new to MongoDB any help will be much appreciate it! thanks.
cron.schedule('0 0 * * *', async () => {
const postSchema = new mongoose.Schema({
id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
status: {
type: String,
required: false
},
});
const Post = mongoose.model('players', postSchema);
async function getPosts() {
const getPlayers = await fetch("http://localhost:3008/api/players");
const response = await getPlayers.json();
for( let i = 0;i < response.players.length; i++){
const post = new Post({
id: response.players[i]['id'],
name: response.players[i]['name'],
status: response.players[i]['status'],
});
post.save();
}
}
console.log("Task submitted successfully")
await getPosts();
});
what i was thinking
const post = await Post.updateMany({
id: response.players[i]['id'],
name: response.players[i]['name'],
status: response.players[i]['status'],
});

I believe you can use bulkWrite and inside bulkWrite you can write updateOne operation with the upsert flag set to true
You can construct an array of operations as follows
let operations = [];
for (let player of players) {
operations.push({
updateOne: {
filter: { id: player.id },
update: { $set: { name: player.name } },
upsert: true,
}
})
}
And finally you can make a call to bulkWrite. Please read the documentation for the operations above

Related

How to stub query helper method Mongoose?

I'm using Sinon to test my Express/Typescript application. In Mongoose I have models with query helper methods to make query chains.
I have this schema
export const articuloSchema = new Schema({
_id: { type: String, default: v4 },
numeroInventario: { type: String, required: true, unique: true },
descripcion: { type: String, trim: true },
}, {
versionKey: false,
query: {
paginate(page: number, limit: number) {
return this.skip(page - 1).limit(limit);
}
}
});
export type ArticuloType = InferSchemaType<typeof articuloSchema>;
export const Articulo = mongoose.model('Articulo', articuloSchema);
and I want to fake my query helper method with Sinon like this
const getMultipleArticulos (): ArticuloType[] => {
const arr:ArticuloType = []
for (let i = 0; i < 5; i++) {
arr.push({
numeroInventario: i,
descripcion: 'string'
})
}
return arr;
}
it('Should return a list of items that belong to a user', function (done) {
const paginateFake = sinon.fake.resolves(getMultipleArticulos());
sinon.replace(Articulo, 'paginate', paginateFake);
chai.request(app)
.get(`/api/v1/users/${userId}/articulos`)
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(200);
// more expects
done();
});
});
The problem is that I cannot stub those methods, it says that it can't stub non existent property of 'paginate' (which is the query helper method I added to my model).

MONGODB store value in variable to use later

i have a code that inserts information from a 3rd party API every 24hours the api information is ID, Name, Status, Position, Score the only information that can get updated if there is any change are Name, Status, Position, Score, ID will always be the same.
I'm trying to show information based on if there is any change when new data is inserted to the database for example
08/14/2022 ------------- 08/15/2022
Name: yandr1 ========== NO CHANGES
position 1 ========== NO CHANGES
id 123 ========== NO CHANGES
score 100 ========== CHANGES TO: 200 ( POINTS GAINED 100 )
based on the new data inserted to MongoDB Database Score changed from 100 to 200, how can i show on the website the OLD SCORE AND POINTS GAINED? Position, Name,old score, POINTS GAINED
CODE TO INSERT DATA INTO DB FROM API
//POST DAILY PLAYERS DATA//
cron.schedule('56 23 * * *', async () => {
const postSchema = new mongoose.Schema({
id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
status: {
type: String,
required: false
},
});
const Post = mongoose.model('players', postSchema);
async function getPosts() {
const getPlayers = await fetch("http://localhost:3008/api/players");
const response = await getPlayers.json();
for (let i = 0; i < response.players.length; i++) {
const post = new Post({
id: response.players[i]['id'],
name: response.players[i]['name'],
status: response.players[i]['status'],
});
post.save();
}
}
console.log("Table submitted successfully")
await getPosts();
});
//POST DAILY HIGHSCORE DATA//
cron.schedule('55 23 * * *', async () => {
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: false
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: false
},
});
const Post = mongoose.model('highscores', postSchema);
async function getPosts() {
const getHighscore = await fetch("http://localhost:3008/api/highscore/players");
const response = await getHighscore.json();
for (let i = 0; i < response.players.length; i++) {
const post = new Post({
position: response.players[i]['position'],
id: response.players[i]['id'],
score: response.players[i]['score'],
});
post.save();
}
}
console.log("Table submitted successfully")
await getPosts();
});
router.get('/export', async function(req, res, next) {
let data
try {
data = await Promise.all([
Posts.list(),
Events.list(),
Messages.list(),
Users.list()
]);
// at this point, data is an array. data[0] = Posts.list result, data[1] = Events.list result etc..
res.status(200).json(data)
} catch (e) {
res.status(500).send('error');
}
});
Hey Yandry try this code-
async function getPosts() {
const getPlayers = await fetch("http://localhost:3008/api/players");
const response = await getPlayers.json();
for( let i = 0;i < response.players.length; i++){
id= response.players[i]['id'];
name= response.players[i]['name'];
status= response.players[i]['status'];
const updateScore = await findOneAndUpdate({id:id},{$set:{name:name,status:status}})
console.log("Updated Score",updateScore)
}
}
Please, try this code, hope you will get solution, if you still facing issue just lemme know, i will help you more.
Thank

Mongoose post save hook, modifiedPaths() is always empty

Our aim is to have a post hook in place where we can track changed fields.
Model file:
const VariationSchema = new Schema({
_id: {
type: String,
},
title: {
type: String,
},
desc: {
type: String,
},
});
VariationSchema.post('save', async function (doc) {
console.log(doc.modifiedPaths());
});
const VariationModel = mongoose.model('variation', VariationSchema);
module.exports = {
VariationModel,
VariationSchema,
};
Service file:
const variationDocument = await VariationModel.findById(variationId).select({});
variationDocument.desc = (Math.random() + 1).toString(36).substring(7);
await variationDocument.save();
return variationDocument.toJSON();
No matter what we do, doc.modifiedPaths() is always empty. Please help

POST array of objects using req.body parser

I am trying to post a simple request which includes array of objects. I have created a model and passing the data as per the model.
I am having trouble accessing body parameters as it contains array of data.
I am able to store line item data by req.body.tasks[0]
which is not a standrad way of storing details in mongodb.
I am looking for a standrad way of storing array of data in mongodb
Controller:
let createBug = (req, res) => {
console.log(req.body.tasks[0].subtask[0].description)
for (var key in req.body) {
if (req.body.hasOwnProperty(key)) {
item = req.body[key];
console.log(item);
}
}
const createBug = new listModel({
title: req.body.title,
tasks: [{
title: req.body.tasks[0].title,
description: req.body.tasks[0].description,
subtask: [{
description: req.body.tasks[0].subtask[0].description
}]
}]
}).save((error, data) => {
if (data) {
let apiResponse = response.generate(false, null, 201, data);
res.status(201).send(apiResponse);
} else {
let apiResponse = response.generate(true, error, 404, null);
res.status(404).send(apiResponse);
}
});
};
body:
{
"title":"sample title",
"tasks":[{
"title": "task 1",
"description":"task1 description",
"subtask":[{
"description":"task3 description"
}]
}]
}
Model:
const mongoose = require("mongoose");
const mySchema = mongoose.Schema;
let subtask = new mySchema({
description: String
})
let taskdata = new mySchema({
title: String,
description: String,
subtask: [subtask]
});
let listSchema = new mySchema({
title: {
type: String,
require: true,
},
tasks: [taskdata],
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: "users",
}
});
module.exports = mongoose.model("list", listSchema);
I think you're overcomplicating things here a little bit. The request body exactly matches the model definitions, so you can simply pass the req.body object to your mongoose model:
const createBug = new listModel(req.body).save((error, data) => { ... }

How to get the array of object instead of just _id in Mongoose

I am very new to mongoose.
I am currently building a backend using Node.js, express.js, GraphQL, and mongoose.
I have a Drink schema and DrinkType Schema. I defined DrinkType schema as "alcohol", "juice", "tea". And I have added many drinks and each drink has DrinkType reference. Then, I would like to reference all the drinks from DrinkType.
This is the schema for drinkType
const drinkTypeSchema = new Schema({
name: {
type: String,
required: true,
},
createdDrinks: [
{
type: Schema.Types.ObjectId,
ref: 'Drink',
},
],
Here is the schema for drink
const drinkSchema = new Schema({
name: {
type: String,
required: true,
},
drinkType: {
type: Schema.Types.ObjectId,
ref: 'DrinkType',
},
})
This is the drink resolver. Whenever a new drink is created, I am pushing it to drinkType.
try {
const result = await drink.save()
createdDrink = transformDrink(result)
const drinkType = await DrinkType.findById(args.addDrinkInput.drinkTypeId)
if (!drinkType) {
throw new Error('DrinkType not found.')
}
drinkType.createdDrinks.push(drink)
await drinkType.save()
const drinkLoader = new DataLoader(drinkIds => {
return drinks(drinkIds)
})
const drinks = async drinkIds => {
try {
const drinks = await Drink.find({ _id: { $in: drinkIds } })
return drinks.map(drink => {
return transformDrink(drink)
})
} catch (err) {
throw err
}
}
const transformDrink = drink => {
return {
...drink._doc,
_id: drink.id,
drinkType: drinkType.bind(this, drink.drinkType),
}
}
const drinkType = async drinkTypeId => {
try {
const drinkType = await drinkTypeLoader.load(drinkTypeId.toString())
return {
...drinkType._doc,
_id: drinkType.id,
createdDrinks: () => drinkLoader.loadMany(drinkType._doc.createdDrinks),
}
I want this createdDrinks part to return the array of drink objects, but it is only returning the array of _ids.
I have been reading the mongoose documentation and it seems that using ObjectId is the correct way. Would you mind helping me out?
Thank you in advance.

Resources