Fetch API Data In Node JS and Save In MongoDB Database - javascript

I'm new to mongooseDB and i'm trying to insert data from this API to the database, it creates the Collection but not the documents, any idea what could i be doing wrong?
import fetch from 'node-fetch';
import mongoose, { mongo } from 'mongoose';
mongoose.connect("mongodb://localhost/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPlayers() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.json();
for (let i = 0; i < response.lenght; i++) {
const post = new Post({
position: response[i]['position'],
id: response[i]['id'],
score: response[i]['score'],
});
post.save()
}
}
getPlayers();```

MongoDB provides Api to insert many documents at the same time, example below.
// check if your mongoDb is connected
mongoose.connect(URI).then(err => {
if(err) console.error({err});
else console.info("Database Connected");
});
async function getPlayers() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
try{
const response = await getPlayers.json();
// And then check if you are getting players
console.log({response});
const posts = response.map((player) => ({
position: player['position'],
id: player['id'],
score: player['score'],
}))
// it's not required to await it, just to be sure it did insert
await Post.insertMany(posts);
}catch(error){
console.log({error})
}
}

This line:
for (let i = 0; i < response.lenght; i++) {
response.length
now your array is empty so the save never happens
EDIT
Are you sure about the imports?
Following code works:
//const fetch = require('fetch');
const mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPlayers() {
/*
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.json();
for (let i = 0; i < response.lenght; i++) {
*/
const post = new Post({
position: '12',
id: '15',
score: '300',
});
post.save()
} //} getPlayers();

Solution:
import fetch from 'node-fetch';
import mongoose, { mongo } from 'mongoose';
mongoose.connect("mongodb://127.0.0.1:27017/highscore");
const postSchema = new mongoose.Schema({
position: {
type: Number,
required: true
},
id: {
type: Number,
required: true
},
score: {
type: Number,
required: true
},
});
const Post = mongoose.model('Players', postSchema);
async function getPosts() {
const getPlayers = await fetch("http://localhost:3008/api/highscore/players");
const response = await getPlayers.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();
}
}
getPosts();

By default mongodb runs on localhost: 27017
Check your mongodb connection url
mongoose.connect('mongodb://localhost:27017/highscore')

Related

How would I make a POST request using Axios to enter two inputs and get data returned?

so I'm trying to make this idea I have come into fruition and I'm having a hard time figuring out where to start. The idea is a Nike Order Check command via discord bot, the user would use '/status' and input their email and order number and the bot would use Axios to get the guest order link 'https://www.nike.com/orders/details/', enter the two inputs the user inputted, click the submit button, then return values. New to using the Axios packages as a whole, so I'm lost on where to start. Does anyone have any ideas? The code below is what I have for before entering the inputs and after the data is captured
const { Discord, CommandInteraction, MessageEmbed } = require('discord.js');
const axios = require('axios');
const requests = require('request')
const wait = require('node:timers/promises').setTimeout;
module.exports = {
name: 'status',
description: 'Check Status Of Nike Order',
permission: 'USE_APPLICATION_COMMANDS',
options: [
{
name: 'email',
description: 'Input Account Email.',
required: true,
type: 'STRING'
},
{
name: 'ordernumber',
description: 'Input Order Number',
required: true,
type: 'STRING'
},
],
/**
*
* #param {CommandInteraction} interaction
*/
async execute(interaction) {
const { options } = interaction;
let email = options.getString("email");
let orderNumber = options.getString("ordernumber");
const baseURL = 'https://www.nike.com/orders/details/';
axios.get(`${baseURL}.json`).then((response) => {
let orderEmbed = new MessageEmbed()
.setTitle('Order Checked 🧪')
.setURL(``)
.addFields(
{ name: '**Account:**', value: `${email}` },
{ name: '**Status:**', value: `` },
{ name: '**Product Name:**', value: ``, inline: true },
{ name: '**Order Date:**', value: ``, inline: true },
{ name: '**Order Number:**', value: `${orderNumber}`, inline: true },
{ name: '**Size:**', value: `` },
)
.setTimestamp()
wait(2000);
interaction.reply({ embeds: [ orderEmbed ]})
})
}
}```
Since there was no answer to how to use axios for this project, I decided to use Puppeteer to integrate into Discord. The following code below is how I got that done.
const { Discord, CommandInteraction, MessageEmbed } = require('discord.js');
const puppeteer = require('puppeteer-extra');
const fs = require('fs');
const ChromeLauncher = require('chrome-launcher');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const Ua = require('puppeteer-extra-plugin-anonymize-ua');
const prompt = require("prompt-sync")({ sigint: true });
const util = require('util');
const UserAgent = require('user-agents');
const request = require('request')
const wait = require('node:timers/promises').setTimeout;
puppeteer.use(StealthPlugin());
puppeteer.use(Ua());
//------------------ Proxy Integration ------------------//
var proxyData = "proxies.json";
function getProxies() {
if (fs.existsSync(proxyData)) {
return JSON.parse(fs.readFileSync(proxyData));
}
var proxies = {
proxies: prompt("Input Proxy List Separated By Commas: ")?.split(/,\s*/) ?? [],
proxyUsername: prompt("Input Proxy Username: "),
proxyPassword: prompt("Input Proxy Password: ")
};
fs.writeFileSync(proxyData, JSON.stringify(proxies));
return proxies [Math.floor(Math.random() * proxies.length)];
}
let { proxies, proxyUsername, proxyPassword } = getProxies();
let proxyList = (`${proxies[Math.floor(Math.random() * proxies.length)]}`);
console.log(proxyList)
module.exports = {
name: 'status',
description: 'Check Status Of Nike Order',
permission: 'USE_APPLICATION_COMMANDS',
options: [
{
name: 'email',
description: 'Input Account Email.',
required: true,
type: 'STRING'
},
{
name: 'ordernumber',
description: 'Input Order Number',
required: true,
type: 'STRING'
},
],
/**
*
* #param {CommandInteraction} interaction
*/
async execute(interaction) {
const { options } = interaction;
let email = options.getString("email");
let orderNumber = options.getString("ordernumber");
await interaction.deferReply();
await wait(1000);
try {
const browser = await puppeteer.launch({
headless: false,
executablePath: `C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe`,
userDataDir: `%LOCALAPPDATA%/BraveSoftware/Brave-Browser/User Data/Default`,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process',
`--enable-auto-reload=true`,
`--proxy-server=http://${proxyList}`
],
})
const page = await browser.newPage()
await page.authenticate({username:proxyUsername, password:proxyPassword});
await page.goto("https://www.nike.com/orders/details/")
await page.evaluate(async() => {
await new Promise(function(resolve) {
setTimeout(resolve, 1000)
});
});
await page.waitForSelector('#orderNumber');
await page.click("#orderNumber", { delay: 250 });
await page.keyboard.type(`${orderNumber}`, { delay: 250 })
await page.waitForSelector('#email');
await page.click('#email', { delay: 500 })
await page.keyboard.type(`${email}`, { delay: 250 })
await page.keyboard.press("Enter", { delay: 250 });
await page.waitForSelector(`p[data-testid="Order Purchase Type"]`)
let purchaseInfo = await page.evaluate(() => {
let purchaseTag = document.querySelectorAll(`p[data-testid="Order Purchase Type"]`);
let purchase = [];
purchaseTag.forEach((tag) => {
purchase.push(tag.innerText)
})
return purchase;
});
await page.waitForSelector(`h3[data-testid="Product Title"]`);
let productInfo = await page.evaluate(() => {
let productTag = document.querySelectorAll(`h3[data-testid="Product Title"]`);
let product = [];
productTag.forEach((tag) => {
product.push(tag.innerText)
})
return product;
});
await page.waitForSelector(`p[data-testid="Product Size"]`);
let productSize = await page.evaluate(() => {
let sizeTag = document.querySelectorAll(`p[data-testid="Product Size"]`);
let size = [];
sizeTag.forEach((tag) => {
size.push(tag.innerHTML)
})
return size;
});
await page.waitForSelector(`div[class="shipment-status-messaging mb3-sm u-full-width"]`);
let deliveryInfo = await page.evaluate(() => {
let deliveryTag = document.querySelectorAll(`div[class="shipment-status-messaging mb3-sm u-full-width"]`);
let delivery = [];
deliveryTag.forEach((tag) => {
delivery.push(tag.innerText)
})
return delivery;
});
await page.waitForSelector(`p[data-testid="Product Style Color"]`);
let skuInfo = await page.evaluate(() => {
let skuTag = document.querySelectorAll(`p[data-testid="Product Style Color"]`);
let sku = [];
skuTag.forEach((tag) => {
sku.push(tag.innerText)
})
return sku.toString();
});
browser.close()
let imgSKU = skuInfo.replace("-", "_")
let updatedSKU = imgSKU.replace("Style ", "")
console.log(updatedSKU)
let orderEmbed = new MessageEmbed()
.setTitle('Order Checked 🧪')
.setColor('#2B2F51')
.addFields(
{ name: '**Account:**', value: `${email}` },
{ name: '**Status:**', value: `${deliveryInfo}` },
{ name: '**Product Name:**', value: `${productInfo}`, inline: true },
{ name: '**Order Date:**', value: `${purchaseInfo}`, inline: true },
{ name: '**Order Number:**', value: `${orderNumber}`, inline: true },
{ name: '**Size:**', value: `${productSize}` },
)
.setTimestamp()
.setThumbnail(`https://images.nike.com/is/image/DotCom/${updatedSKU}?/$OMEGA_PRODUCT$.png`)
wait(2000);
interaction.editReply({ embeds: [ orderEmbed ]})
} catch (error) {
const errorEmbed = new MessageEmbed()
errorEmbed.setTitle('❌ Error Encountered ❌')
errorEmbed.setDescription('No variants/product found')
errorEmbed.setTimestamp()
interaction.editReply({ embeds: [ errorEmbed ]})
}
}
}

Mongoose Which one is faster .populate() or .find()

I want to get posts related to a user. which one is faster
to find the User and populate posts
User.findOne({ _id: id}).populate("posts")
Or to search in the Posts model Directly
Post.find({ owner: user_id })
This benchmark code suggests that Post.find({ owner: user_id }) is somewhat faster.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const NUM_USERS = 100;
const NUM_POSTS_PER_USER = 10;
mongoose.connect('mongodb://localhost:27017/testdb', { useNewUrlParser: true });
const userSchema = Schema({
posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});
const postSchema = Schema({
owner: { type: Schema.Types.ObjectId, ref: 'User' },
title: String,
content: String,
});
const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', postSchema);
const userIds = [];
async function seed() {
await User.deleteMany({});
await Post.deleteMany({});
for (let i = 0; i < NUM_USERS; ++i) {
const user = new User();
await user.save();
for (let i = 0; i < NUM_POSTS_PER_USER; ++i) {
const post = new Post({
owner: user,
title: Array(50).fill('a').join(''),
content: Array(1000).fill('b').join(''),
});
await post.save();
user.posts.push(post);
}
await user.save();
userIds.push(user._id);
}
}
async function benchmarkPopulate() {
console.time('populate');
for (const id of userIds) {
await User.findOne({ _id: id }).populate("posts");
}
console.timeEnd('populate');
}
async function benchmarkFind() {
console.time('find');
for (const user_id of userIds) {
await Post.find({ owner: user_id });
}
console.timeEnd('find');
}
async function main() {
await seed();
await benchmarkPopulate();
await benchmarkFind();
await benchmarkPopulate();
await benchmarkFind();
await mongoose.disconnect();
}
main();
Output:
populate: 217.534ms
find: 121.905ms
populate: 169.181ms
find: 120.171ms
This is not surprising since Post.find({ owner: user_id }) only needs to query one collection.
These results are fairly consistent across runs (and even if you reverse the order of the benchmarks).
Your mileage may vary and this difference doesn't really matter, especially if you're querying the database over a network.

mongoose find returning empty array even their is a value on the database

I'm trying to add commodity data to my stockrecord collection and if the commodity name is already in the stockrecord collection I just want to add the quantity of the commodity quantity to my stockrecord quantity.
but even their is existing data the, find method is returning an empty array
This my code
commodity.map(async (e) => {
const data = await new Commodity({
name: e.commodityName,
units: e.units,
quantity: e.quantity,
});
data.donator = donator;
await data.save();
const stock = await StockRecord.find({
name: {
$eq: e.commodityName,
},
});
//console.log(stock);
if (stock.length === 0) {
const record = await new StockRecord({
name: e.commodityName,
units: e.units,
quantity: parseFloat(e.quantity),
});
await record.save();
console.log(record);
} else {
console.log('may sulud');
stock[0].quantity += parseFloat(e.quantity);
await stock[0].save();
}
});
This is my stockrecord model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const stockRecordSchema = new Schema({
name: {
type: String,
},
units: {
type: String,
enum: \['kg', 'pcs'\],
},
quantity: {
type: Number,
},
});
Array.map does not accept Promises
Try using for (const item of commodity) { //async magic here }

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;

Promise in cron job

I try to run the code without success.
Only the first call works in start of node.
Here is my current code:
const Product = require('../models/Product');
const Price = require('../models/Price');
const cron = require('node-cron');
const amazon = require('amazon-product-api');
const util = require('util');
const _ = require('underscore')
/**
* Cron job
* Tracking price
*/
exports.track = () => {
cron.schedule('* * * * *', () => {
const client = amazon.createClient({
awsId: process.env.AWS_ID,
awsSecret: process.env.AWS_SECRET,
assocId: process.env.AWS_TAG
});
Promise.all([Product.getAsin()])
.then(([asin]) => {
let listId = _.pluck(asin, '_id');
let listAsin = _.pluck(asin, 'asin');
if (asin.length === 0) {
return
}
client.itemLookup({
idType: 'ASIN',
itemId: listAsin,
domain: 'webservices.amazon.fr',
responseGroup: 'ItemAttributes,OfferFull,SalesRank'
}).then((results) => {
for(i=0; i<listId.length; i++){
results[i].id = listId[i];
}
for(res of results) {
Price.addPrice({
asin: res.ASIN[0],
product: res.id,
salePrice: res.Offers[0].Offer[0].OfferListing[0].Price[0].Amount[0],
})
}
console.log(listId);
Product.makeUpdate(listId);
}).catch(function(err) {
console.log(err);
console.log(util.inspect(err, true, null));
});
})
.catch((err) => {
console.log(err);
})
})
}
Requests to MongoDB are asynchronous.
Product
const mongoose = require('mongoose');
mongoose.Promise = Promise;
const _ = require('underscore');
const moment = require('moment');
const productSchema = new mongoose.Schema({
name: String,
domain: String,
originUrl: { type: String, unique: true },
check: { type: Number, default: 0 },
ean: String,
asin: String
}, { timestamps: true });
Object.assign(productSchema.statics, {
getAsin() {
return this.find(
{ updatedAt: { $lt: oneMin },
asin: { $ne: null }
}
).limit(10)
.select({ asin: 1 })
.exec()//.then((tuples) => _.pluck(tuples, 'asin'))
},
makeUpdate(id) {
console.log('list des ID updated => ' + id);
return this.update({ _id: { $in: id } }, { $inc : { "check": 1 } } , {multi: true}).exec();
}
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
const oneMin = moment().subtract(1, 'minutes').format();
Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)

Categories

Resources