Writing a database seeder class to seed multiple collections. (NodeJS, MongoDB) - node.js

Hi all I have been struggling all day with this and I was hopingsomeone might be able to assist me on figuring out the functionality. I'm still very new to asynchronous programming so any advice would be highly appreciated! I wrote two seeder classes which work great independently, and am opting to create a databaseSeeder class that I can use to run all my migrations from one file.
The issue I'm facing is that I need the UserSeeder to complete first because the ProductSeeder uses the ID's from the User model to link products to users. Please find my code for a reference:
User Seeder:
const mongoose = require("mongoose");
const User = require("../models/User");
const dotenv = require("dotenv");
const { faker } = require("#faker-js/faker");
const { v4: uuidv4 } = require("uuid");
dotenv.config();
const database = process.env.MONGOLAB_URI;
mongoose
.connect(database, {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => console.log("User Collection Connected"))
.catch((err) => console.log(err));
const seedUserList = async () => {
let users = [];
for (let i = 0; i < 5; i++) {
const userSeeder = new User({
_id: uuidv4(),
firstname: faker.name.firstName(),
lastname: faker.name.lastName(),
username: faker.internet.userName(),
email: faker.internet.email(),
contact_number: faker.phone.number("### ### ####"),
password: faker.internet.password(),
address: faker.address.streetAddress(),
avatar: faker.image.people(1920, 1080, true),
rating: 3,
isVerified: false,
isValidated: false,
});
users.push(userSeeder);
}
const seedUsers = async () => {
await User.deleteMany({});
await User.insertMany(users);
};
seedUsers().then(() => {
console.log("Users Seeded Successfully!");
mongoose.connection.close();
});
};
seedUserList();
module.exports = {
seedUserList,
};
Product Seeder:
const mongoose = require("mongoose");
const Product = require("../models/Product");
const User = require("../models/User");
const dotenv = require("dotenv");
const { faker } = require("#faker-js/faker");
const { v4: uuidv4 } = require("uuid");
dotenv.config();
const database = process.env.MONGOLAB_URI;
mongoose
.connect(database, {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => console.log("Products Collection Connected"))
.catch((err) => console.log(err));
const seedProductList = async () => {
let products = [];
let ids = [];
let idList = await User.find().select("_id");
idList.map((r) => r.toObject());
for (let i = 0; i < idList.length; i++) {
idList[i] = JSON.stringify(idList[i]);
ids.push(idList[i].substring(8, 44));
}
for (let i = 0; i < 25; i++) {
const productSeeder = new Product({
_id: uuidv4(),
name: faker.commerce.product(),
price: faker.commerce.price(),
description: faker.commerce.productDescription(),
image: faker.image.image(1920, 1080, true),
category: "Tools",
times_borrowed: faker.datatype.number(),
last_borrowed: faker.date.past(),
product_status: faker.helpers.arrayElement(["Available", "In Use"]),
user_id: faker.helpers.arrayElement(ids),
});
products.push(productSeeder);
}
const seedProducts = async () => {
await Product.deleteMany({});
await Product.insertMany(products);
};
seedProducts().then(() => {
console.log("Products Seeded Successfully!");
mongoose.connection.close();
});
};
seedProductList();
module.exports = {
seedProductList,
};
Database Seeder:
const { seedUserList } = require("./userSeeder");
const { seedProductList } = require("./productSeeder");
const mongoose = require("mongoose");
const seedDatabase = async () => {
seedUserList().then(() => {
console.log("Seeding Users!");
});
await seedProductList().then(() => {
console.log("Seeding Products!");
});
};
seedDatabase().then(() => {
console.log("Database Successfully Seeded!");
mongoose.connection.close();
});
Terminal Output
E:\Projects\Shopping-Platform>node src/seeders/databaseSeeder.js
Seeding Users!
User Collection Connected
Products Collection Connected
Seeding Products!
Database Successfully Seeded!
Products Seeded Successfully!
Users Seeded Successfully!
I've been playing around with the await functionality and wrapping each function with it's own await call so that the ProductSeeder waits for the UserSeeder to complete first before it executes, but so far no luck!

Related

Mongo DB SORTING data nodejs

i created a code that Backsup/Deletes and Inserts information from the Third Party API every 24hours to update the Third party api changes daily on the database.
how can i sort the information i get from the MongoDB by which score changed the most?
API LOOKS LIKE
{
"_id": "6365e1dbde0dd3639536f4b7",
"position": 1,
"id": "105162",
"score": 2243536903,
"__v": 0
},
MY CODE
app.get('/api/TopFlops', async (req, res) => {
const topflops = await TopFlops.find({}).sort({_id: +1}).limit(5)
res.json(topflops);
})
CODE TO INSERT DATA FROM THE 3RD PARTY API TO DB
cron.schedule('59 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();
});
CODE TO FETCH API
const [playerName, setPlayerName] = useState([]);
const [playerRank, setPlayerRank] = useState([]);
const [player, setPlayer] = useState([]);
const [perPage, setPerPage] = useState(10);
const [size, setSize] = useState(perPage);
const [current, setCurrent] = useState(1);
const [players, setPlayers] = useState();
const fetchData = () => {
const playerAPI = 'http://localhost:3001/api/topflops';
const playerRank = 'http://localhost:3001/api/topflops';
const getINFOPlayer = axios.get(playerAPI)
const getPlayerRank = axios.get(playerRank)
axios.all([getINFOPlayer, getPlayerRank]).then(
axios.spread((...allData) => {
const allDataPlayer = allData[0].data
const getINFOPlayerRank = allData[1].data
const newPlayer = allDataPlayer.map(name => {
const pr = getINFOPlayerRank.find(rank => name.id === rank.id)
return {
id: name.id,
name: name.name,
alliance: name.alliance,
position: pr?.position,
score: pr?.score
}
})
setPlayerName(allDataPlayer)
setPlayerRank(getINFOPlayerRank)
console.log(getINFOPlayerRank)
console.log(newPlayer)
setPlayer(newPlayer)
})
)
}
useEffect(() => {
fetchData()
}, [])
const getData = (current, pageSize) => {
// Normally you should get the data from the server
return player?.slice((current - 1) * pageSize, current * pageSize);
};

Create private chat with MERN and Socketio

i want to send message to specific user from react-autocomplete dropdown menu with select and display that message in their own window. And also i am trying to save messages to my mongodb but when i check mongocompass server it is only showing me the _id and and when i click send button in front end it is sending same message multiple times .Here is what i have so far but it is sending the message to everyone. i need help to get my code right to create private chat with saving correctly to db and retrieve messages everytime page refreshes
CLIENT:
const [username, setUsername] = useState("");
const [onlineUsers, setOnlineUsers] = useState([]);
const [chatHistory, setChatHistory] = useState([]);
const ADDRESS = "http://localhost:1337";
const socket = io(ADDRESS, { transports: ["websocket"] });
useEffect(() => {
socket.on("connect", () => {
console.log("Connection established!");
});
socket.on("loggedIn", () => {
console.log("Successfully logged in");
fetchOnlineUsers();
});
socket.on("newConnection", () => {
console.log("Look! another client connected!");
fetchOnlineUsers();
});
socket.on("message", (newMessage) => {
console.log("new message received!", newMessage);
setChatHistory((currentChatHistory) => [
...currentChatHistory,
newMessage,
]);
});
}, []);
const handleSubmitMessage =(e)=> {
e.preventDefault();
const messageToSend = {
text: message,
sender: username,
id: socket.id,
timeStamp: Date.now()
}
socket.emit("sendmessage", messageToSend)
setChatHistory([...chatHistory, messageToSend])
setMessage("")
}
const handleOnSearch = (string, results) => {}
const handleOnHover = (result) => {}
const handleOnSelect = (item) => {
console.log("ITEM",item);
}
const handleOnFocus = () => {}
const formatResult = (item) => {
return (
<>
<span style={{ display: 'block', textAlign: 'left' }}>{item.username}</span>
</>
)
}
SERVER CODE
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import listEndpoints from "express-list-endpoints";
import { Server } from "socket.io";
import { createServer } from "http";
import MsgModel from './db/schema.js'
const { MONGO_URL } = process.env;
const app = express();
app.use(cors());
app.use(express.json());
const server = createServer(app);
const io = new Server(server);
const port = process.env.PORT || 1337;
let onlineUsers = [];
io.on("connect", (socket) => {
socket.join("main-room")
socket.on("setUsername", ({ username }) => {
onlineUsers = onlineUsers
.filter((user) => user.username !== username)
.concat({
username: username,
id: socket.id,
});
socket.emit("loggedIn");
socket.broadcast.emit("newConnection");
});
socket.on("sendmessage", (msg) => {
console.log("sendmessage",msg);
const saveMessageToDb = new MsgModel({msg:msg})
saveMessageToDb.save().then(()=> {
socket.to("main-room").emit("message", msg)
})
})
app.get("/online-users", (req, res) => {
res.send({ onlineUsers });
});
MONGOOSE SCHEMA
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const msgSchema = new Schema(
{
msg: { type: String },
},
{ typeKey: '$type' }
);
export default model("Message", msgSchema);

GraphQL Mongoose with MongoDB Atlas return empty array

I'm trying to connect MongoDB Atlas and mongoose but server always returns an empty array '[ ]'. When I load a mock data everything works (Mocked data and MongoDB Atlas have the same values)
I have connect to MongoDB Atlas, but can't get some data.
Controller:
const express = require('express')
const { ApolloServer } = require('apollo-server-express')
const { createServer } = require('http')
const mongoose = require('mongoose')
const typeDefs = require('./schema')
const resolvers = require('./resolvers')
const app = express()
const server = new ApolloServer({
typeDefs,
resolvers,
playground: {
endpoint: 'http://localhost:3000/graphql',
settings: {
'editor.theme': 'light'
}
}
})
server.applyMiddleware({ app })
const httpServer = createServer(app)
server.installSubscriptionHandlers(httpServer)
mongoose
.connect(`mongodb+srv://<username>:<password>#cluster0.brdqp.mongodb.net/${process.env.mongoDatabase}?retryWrites=true&w=majority`, { useNewUrlParser: true, useUnifiedTopology: true })
.then((res) => {
httpServer.listen(3000, () => {
console.log('connected!')
})
})
.catch((err) => {
console.error('Error while connecting to MongoDB', err);
})
Schema:
const { gql } = require('apollo-server-express')
const typeDefs = gql`
type Todo {
_id: String,
title: String,
description: String
status: String
date: String
}
type Query {
todos: [Todo]
}
`
module.exports = typeDefs
Resolvers:
const { Todo, Restaurant, Customer, Order } = require('./models')
const pubsub = require('./pubsub')
const resolvers = {
Query: {
todos(parent, args, context, info) {
return Todo.find()
.then(todo => {
return todo.map(r => ({ ...r._doc }))
})
.catch(err => {
console.error(err)
})
},
},
}
module.exports = resolvers
MongoDB Atlas collection: (Database name : node, collection name in DB : todo)
_id : 5c9bdb721c9d440000345d62
title : "question"
desctiption : "test test"
status: done
date: 1
But the server always returns [ ]
How???? Why&?

HOW TO FIX Mongoose 5.11.8 model.find() ERROR Operation `thanks-leaderboards.find()` buffering timed out after 10000ms

How to solve model.find() function produces "buffering timed out after ... ms"? I'm using mongoose v 5.11.8, npm v6.14.8 and mongodb v3.6.3
Here's the code.
thanks-leaderboard.js
const thanksLeaderboardSchema = require('../../schemas/thanks-leaderboard-schema.js')
const thanksSchema = require('../../schemas/thanks-schema.js')
const fetchTopMembers = async (guildId) => {
let text = ''
const results = await thanksSchema
.find({
guildId,
})
.sort({
received: -1,
})
.limit(10)
for (let counter = 0; counter < results.length; ++counter) {
const { userId, received = 0 } = results[counter]
text += `#${counter + 1} <#${userId}> with ${received} thanks\n`
}
text += '\nThis is updated every minute'
return text
}
const updateLeaderboard = async (client) => {
const results = await thanksLeaderboardSchema.find({}).where('channelId')
for (const result of results) {
const { channelId, _id: guildId } = result
const guild = client.guilds.cache.get(guildId)
if (guild) {
const channel = guild.channels.cache.get(channelId)
if (channel) {
const messages = await channel.messages.fetch()
const firstMessage = messages.first()
const topMembers = await fetchTopMembers(guildId)
if (firstMessage) {
firstMessage.edit(topMembers)
} else {
channel.send(topMembers)
}
}
}
}
setTimeout(() => {
updateLeaderboard(client)
}, 1000 * 60)
}
module.exports = async (client) => {
updateLeaderboard(client)
}
set-leaderboard.js
const leaderBoardSchema = require('../../schemas/thanks-leaderboard-schema.js')
module.exports = {
commands: 'setleaderboard',
requiredRoles: ['Administrator'],
description: 'Erstelle ein Leaderboard für die vergebenen Danksagungen',
callback: async (message) => {
const { guild, channel} = message
const guildId = guild.id
const channelId = channel.id
await leaderBoardSchema.findOneAndUpdate({
_id: guildId,
channelId,
},
{
_id: guildId,
channelId,
},
{
upsert: true,
})
message.reply('Leaderboard wurde erstellt!').then((message) => {
message.delete({
timeout: 1000 * 5,
})
})
message.delete()
}
}
thanks-leaderboard-schema.js
const mongoose = require('mongoose')
const reqString = {
type: String,
required: true,
}
const thanksLeaderboardSchema = mongoose.Schema({
// Guild ID
_id: reqString,
channelId: reqString,
})
module.exports = mongoose.model('thanks-leaderboards', thanksLeaderboardSchema, 'thanks-leaderboards')
thanks-schema.js
const mongoose = require('mongoose')
const reqString = {
type: String,
required: true,
}
const thanksSchema = mongoose.Schema({
userId: reqString,
guildId: reqString,
received: {
type: Number,
default: 0,
},
lastGave: Date,
})
module.exports = mongoose.model(
'thanks',
thanksSchema,
'thanks'
)
I tried increasing the bufferTimeoutMS or disabling the bufferCommands but still it won't work. This Code is supposed to readout the database every 60 seconds but the timeout happens after 10 seconds... can't figure out how to fix this error. I've already tried to delete the node_modules folders for mongoose and mongodb and reinstall them via npm but that didn't work as I get this error again.

Mongoose transaction over separate databases

I am trying to create a transaction to create documents in two separate databases using Mongoose. I wrote this piece of code, it creates docs in the databases, but when if I throw an error in the code, the docs still appear in the db's. Can anybody help me figure out what I do wrong?
const mongodb = mongoose.createConnection(MONGODB_URL, mongoOptions);
const session = await mongodb.startSession();
session.startTransaction();
try {
let db = mongodb.useDb('superUs');
const OrgModel = db.model('Organization', Organization, 'Organizations');
const newOrg = OrgModel.create([org, { session }]);
db = mongodb.useDb('anotherDb');
const UtilRecModel = db.model('User', User, 'util');
const NewUtilRec = UtilRecModel
.create([{ username: 'user', password: 'pwd', isAdmin: false }, { session }]);
session.commitTransaction();
session.endSession();
} catch(err) {
session.abortTransaction();
console.log('err');
}
const dbName = `organization-${org.title}`;
let sessionSuper;
let sessionOrg;
try {
const dbSuper = mongodb.useDb('superUs');
const dbOrg = mongodb.useDb(dbName);
const OrgModel = dbSuper.model('Organization', Organization, 'Organizations');
const UtilRecModel = dbOrg.model('User', User, 'util');
sessionSuper = await dbSuper.startSession();
sessionOrg = await OrgModel.startSession();
sessionSuper.startTransaction();
sessionOrg.startTransaction();
await OrgModel.create([org], { session: sessionSuper });
await UtilRecModel.create([{ username: 'util', password: 'util', isAdmin: false }], { session: sessionOrg });
sessionSuper.commitTransaction();
sessionSuper.endSession();
sessionOrg.commitTransaction();
sessionOrg.endSession();
} catch(err) {
sessionSuper.abortTransaction();
sessionOrg.abortTransaction();
sessionSuper.endSession();
sessionOrg.endSession();
throw(err);
}

Resources