append data to an existing Json file in nodejs - node.js

i'm trying to add new data in an existing json file named db.json which i use to store data locally aka inMemory.So i tried many ways to achieve that but still not working as expected Since the add operation replaced the existing data.
For example i want something like this :
{
"users": [,
{
"email": "johnDoe#gmail.com",
"password": "blabala",
"firstname": "John",
"lastname": "Doe",
"address": "4 rue gay lussac",
"city": "Paris",
},
{
"email": "new email",
"password": "new password",
"firstname": "new firstname",
"lastname": "new lastname",
"address": "new address",
"city": "new city",
}
],
}
i'm currently working in nodejs using the writeFileSync() method from fs library.
My index.js looks like this :
server.post("/register", (req, res) => {
const {firstname, lastname, email, password,address, city} = req.body
if(firstname && lastname && email && password && address && city) {
try {
fs.readFile("db.json")
fs.writeFileSync(path.join(__dirname, "db.json"),JSON.stringify(req.body), {encoding: "utf-8"})
res.status(201).send({
message: "User created!"
})
} catch (error) {
res.status(500).send({
code: error.code,
message: error.message
})
}
}else{
res.status(500).send({
message: "Something wrong"
})
}
})
Need some suggestions please. Thks!!

I did almost the same thing as you long time ago, you have to extract the content of the file as a JSON Object, modify it and then write it stringifyied in your file.
I still have a snippet of what I've done in the past:
const getUsers = () => {
let users = fs.readFileSync(path.join(__dirname, '../workspace/.users.json'));
return JSON.parse(users);
};
const setUsers = (users) => {
let newUsersObject = JSON.stringify(users, null, 2);
fs.writeFileSync(path.join(__dirname, '../workspace/.users.json'), newUsersObject);
};
So with this two functions you can do things like:
//retrieve users
let userObject = getUsers();
//edit the first user (example)
userObject[0].firstname = "John";
userObject[1].lastname = "Doe";
//save the modified object
setUsers(userObject);

Related

Trying to display single user

I'm trying to create this logic a whole day and can't find anything helpful.. A small introduce of my app: While studying, I'm creating my local date app as practical job to improve more skills and logics. The problem is that I'm trying to get single user in main(home) page, when user login it should see already loaded single user from MongoDB where he can click like or dislike button. When user clicks one of them this user will push in user liked or dislike array and next user displays. I don't have like system yet, cause I can't get a single user. So later I wanna do filter method if user already liked or disliked other user, that one user didn't appear anymore and let users view his liked and disliked users.
So the main thing is that I have a get method where I'm getting all users and tried to create different routes to get only one of them, but can't imagine how to create correct logic of that.. 4-5 hours ago I tried to make for, map, forEach cycles but still can't understand the main logic here..
Here's my code, if it's not enough to understand just ask me for more code.
mainController(back-end):
getSingleUser: async (req, res) => {
const { secret } = req.params;
const findUser = await UserSchema.findOne({ secret });
if (findUser) {
return res.send({ error: false, message: 'User found', data: findUser });
}
return res.send({ error: true, message: 'User not found', data: null });
},
getAllUsers: async (req, res) => {
try {
const allUser = await UserSchema.find({});
res.status(200).json(allUser);
} catch (error) {
res.status(400).json({ message: error.message });
}
}
mainRouter(back-end):
const express = require('express')
const { login, register, getSingleUser, getAllUsers } = require("../controller/mainController")
const { loginValidate, registerValidate } = require("../middleware/authValidator")
const mainRouter = express.Router()
mainRouter.post('/register', registerValidate, register);
mainRouter.post('/login', loginValidate, login);
mainRouter.get('/api', getAllUsers)
mainRouter.get('/user/:secret', getSingleUser)
module.exports = mainRouter;
HomePage(front-end):
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import Toolbar from '../components/Toolbar';
import { get } from '../helper/helper';
import SingleUser from '../components/SingleUser';
export default function HomePage() {
const [allUsers, getAllUsers] = useState([])
const secret = window.localStorage.getItem('secret')
useEffect(() => {
async function fetchUsers() {
const resp = await get('api')
getAllUsers(resp)
}
fetchUsers()
}, [])
return (
<div className='home__page'>
<Toolbar />
<div className="home__users">
{allUsers && allUsers.filter(user => user.secret !== secret).map((users, i) => <SingleUser users={users} key={i} />)}
</div>
<footer className='footer'>
<p>All rights reserved by Cartoon Match organization. To read more about our policy <Link to='/policy'>click here</Link>. </p>
</footer>
</div>
)
}
This is result of HomePage users fetch:
[
{
"_id": "638e31a2579ba2a13b454943",
"image": [
"https://picsum.photos/id/377/4884/3256",
"https://picsum.photos/id/378/5000/3333"
],
"username": "testas",
"firstName": "testas",
"lastName": "testas",
"email": "test#gmail.com",
"gender": "male",
"city": "asdadas",
"country": "aasdasd",
"birth": "2020-02-20",
"phone": "65asd15a6sd",
"password": "$2b$04$zpqQVU7cFUfdA9DCfKmFYOOdY93OVPXoQq08kM87ehwwxD25/pl6q",
"likes": [],
"liked": [],
"secret": "Ey2_-dVlpg",
"__v": 0
},
{
"_id": "639130a43c2e51dc08531019",
"image": [
"https://www.1zoom.me/big2/98/183590-20043.jpg",
"https://pngimg.com/uploads/shrek/shrek_PNG22.png"
],
"username": "SirShrek",
"firstName": "Sir",
"lastName": "Shrek",
"email": "callmeshrek#swamp.com",
"gender": "male",
"city": "Swamp",
"country": "Fairy-Tale Land Of Duloc",
"birth": "1999-02-27",
"phone": "830-476-5664",
"password": "$2b$04$u1jacGrx6yWOMxfkllMxWO.5in4rQDFIbbCMMixzHqV9rObtq1tKG",
"likes": [],
"liked": [],
"secret": "FP8Rd4izgQ",
"__v": 0
},
{
"_id": "6391c8df7f83052432e2d939",
"image": [
"https://static.wikia.nocookie.net/vsbattles/images/e/e8/Dexter_Rendered.png/revision/latest?cb=20180919045250",
"https://i.ebayimg.com/images/g/VesAAOSwrohehKhn/s-l1600.jpg"
],
"username": "Dexter",
"firstName": "Dexter",
"lastName": "Michael Louis McPherson lll",
"email": "dexter#science.com",
"gender": "male",
"city": "Genius Grove",
"country": "Peter Lorre",
"birth": "2014-12-31",
"phone": "555-0100",
"password": "$2b$04$BMUidKOaRBtWDNKH.NduB.gkgzUhPNuXVk10ip7lPo/N/1k/8sxvW",
"likes": [],
"liked": [],
"dislike":[],
"secret": "9k6ilC2ZZg",
"__v": 0
}]
This is SingleUser component:
import React, { useEffect, useState } from "react";
import MainContext from '../context/MainContext'
import { get, put } from '../helper/helper'
export default function SingleUser({ users }) {
return (
<div className='single__user'>
<img src={users.image[0]} alt="" />
<h3>{users.firstName} {users.lastName}</h3>
<h4>{users.gender}</h4>
<button>Dislike</button>
<button onClick={postLikes}>Like</button>
</div>
);
}

How to filter mongoDB in NodeJS API, checking if values are included in objects in array

I am writing REST API in NodeJS with MongoDB. Structure of the database is:
[
{
"_id": "12345",
"name": "Meal name",
"category": "dessert",
"area": "british",
"imageUrl": "https.image.jpg",
"instructions": "some instructions...",
"ingredients": [
{
"name": "salt",
"measure": "1g"
},
{
"name": "chicken",
"measure": "1"
},
{
"name": "butter",
"measure": "90g"
}, ...
]
}, ...
]
I can write a route to get data which meet one condition,
i.e.:
//getting all, when category = :category
router.get('/meals/category=:category', async (req, res) => {
try {
const meals = await Meal.find({category: req.params.category})
res.json(meals)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
Here, route
'meals/category=vegetarian'
get all data with category = vegetarian.
However, I want to have route, which will filter all data by parameters: category, area, ingredients.
For example:
meals/ingredients=salt,pepper&category=dessert&area=american
should return all data, which contains salt and pepper in array, and category = dessert.
another example:
meals/area=american&category=dessert
should return all data, where area=american and category=dessert
How can I write the router.get() method to achieve that?

Save user ID in JSON file

Today I'm trying to make a json data to link discord account to another account (League of Legends, Dota, etc...)
To make my database, I'm using this code:
message.reply(`Your account is link to **${args[1]}**`).then(msg => {
msg.delete({
timeout: 5000
});
});
userID = message.author;
let link = require('../link.json')
link.userID = {
name: `${message.author.username}`,
lol: `${args[1]}`,
}
var string = JSON.stringify(link, null, '\t');
fs.writeFile('./link.json', string, function(err) {
if (err) return console.error(err);
})
If bob writes /link lol boby02 and I (StarKleey 帅哥) write /link lol StarKleey the json will be:
{
"userID": { //here I would like "#<565465478767545>": {
"name": "bob",
"lol": "boby02"
},
"userID": { //and here "#<456465574385735>": {
"name": "StarKleey 帅哥",
"lol": "StarKleey"
}
}
How can I do that?
This is what I'm currently using:
link.message.author = {
name: `${message.author.username}`,
lol: `${args[1]}`,
}
Reload :
{
"#<565465478767545>": {
"name": "bob",
"lol": "boby02"
},
"#<456465574385735>": {
"name": "StarKleey 帅哥",
"lol": "StarKleey"
}
}
You're currently storing the username, while you seem to want to store the user id: you should try using User.id:
link.message.author = {
name: `${message.author.id}`,
lol: `${args[1]}`,
}

How to build a search endpoint in a API to find and filter results from a database

In my Node API and MongoDB, I'm trying to build an endpoint to search for data in the DB and get back the results to the client. My search goal is to show results from the Profile collection and in that way, I can build my queries to search by first name, surname, company and the combination of it as an example:
GET search?fn=joe or ?ln=doe or ?cp=Company or ?fn=...&ln=...&cp=...
Practically I can search in different ways and I can get for example all the people working for a company as a result of a search.
I would like to understand how can I achieve that with Mongoose/MongoDB and add also to the query optional a limit/pagination for the coming results.
I tried to make some simple trials but I got stuck as I do not really get it how to proceed next.
const SearchController = {
async getQuery(req, res) {
try {
const { fn, ln, cp } = req.query;
const searchResult = await Profile.find({
$or: [
{ firstname: fn },
{ surname: ln },
{
experience: {
company: cp
}
}
]
});
res.status(200).json(searchResult);
} catch (err) {
res.status(500).json({ message: err.message });
}
}
};
The JSON of a profile:
{
"imageUrl": "https://i.pravatar.cc/300",
"posts": [
"5e3cacb751f4675e099cd043",
"5e3cacbf51f4675e099cd045",
"5e3cacc551f4675e099cd046"
],
"_id": "5e2c98fc3d785252ce5b5693",
"firstname": "Jakos",
"surname": "Lemi",
"email": "lemi#email.com",
"bio": "My bio bio",
"title": "Senior IT developer",
"area": "Copenhagen",
"username": "Jakos",
"experience": [
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-04T13:47:37.167Z",
"updatedAt": "2020-02-04T13:47:37.167Z",
"_id": "5e3975f95fbeec9095ff3d2f",
"role": "Developer",
"company": "Google",
"startDate": "2018-11-09T23:00:00.000Z",
"endDate": "2019-01-05T23:00:00.000Z",
"area": "Copenhagen"
},
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-04T13:59:27.412Z",
"updatedAt": "2020-02-04T13:59:27.412Z",
"_id": "5e3978bf5e399698e20c56d4",
"role": "Developer",
"company": "IBM",
"startDate": "2018-11-09T23:00:00.000Z",
"endDate": "2019-01-05T23:00:00.000Z",
"area": "Copenhagen"
},
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-07T16:35:43.754Z",
"updatedAt": "2020-02-07T16:35:43.754Z",
"_id": "5e3d91dfb3a7610ec6ad8ee3",
"role": "Developer",
"company": "IBM",
"startDate": "2018-11-10T00:00:00.000Z",
"endDate": "2019-01-06T00:00:00.000Z",
"area": "Copenhagen"
}
],
"createdAt": "2020-01-25T19:37:32.727Z",
"updatedAt": "2020-02-04T23:14:37.122Z",
"__v": 0
}
The expected results are for example if I search the first name Joe I should get back all the profiles having as first name Joe. Similar for surname and company.
Please provide comments to allow me to understand if you need more scripts from the original code to see.
EDITED added the code modified of the search
// Models
const { Profile } = require("../models");
// Error handling
const { ErrorHandlers } = require("../utilities");
const SearchController = {
async getQuery(req, res) {
try {
const { fn, ln, cp } = req.query;
const query = {
$or: []
};
if (fn) query.$or.push({ firstname: fn });
if (ln) query.$or.push({ surname: ln });
if (cp) query.$or.push({ "experience.company": cp });
const searchResult = Profile.find(query, docs => {
return docs
});
if ((await searchResult).length === 0)
throw new ErrorHandlers.ErrorHandler(
404,
"Query do not provided any result"
);
res.status(200).json(searchResult);
} catch (err) {
res.status(500).json({ message: err.message });
}
}
};
module.exports = SearchController;
Have tried conditional query and modified your array search query for finding the company,
function findUser(fn, ln, cp) {
const query = {
$or: []
}
if (fn) query.$or.push({ firstname: fn })
if (ln) query.$or.push({ surname: ln })
if (cp) query.$or.push({ "experience.company": cp })
Profile.find(query, function (err, docs) {
if (err) {
console.error(err);
} else {
console.log(docs);
}
});
}
findUser("","","IBM")

Parsing arrays within array for email in Node.js

I am submitting an array that contains nested arrays from Angular to a server running Node.js. I would like to parse each field so I can include it in a confirmation email. I'm not sure how to get the key/values from the array and put them in the email body.
I've tried var email = req.body.email for the items one level deep and var cost = req.body.detail.cost for the nested items two levels deep, but those don't seem to work.
Any suggestions?
Here's the Javascript:
router.post('/', function(req, res) {
if (err) {
res.status(402).send(err.message);
}
else {
console.log(JSON.stringify(req.body, null, 2));
var data = {
from: storefront#example.com,
to: email,
subject: 'Your Order Confirmation',
text: 'Thank you for your order. Below is your invoice:\n\n'+
'Name: '+ firstName + ' ' + lastName +
'Address: ' + address + ', ' + city + ', ' + state.code +'\n\n'+
'Item Description Cost\n\n'+
item + description + cost
// want to add the item, description, and cost for each item ordered
// . . .
var mailgun = new Mailgun({apiKey: api_key, domain: domain});
mailgun.messages().send(data, function (err, body) {
if (err) {
console.log('error');
}
else {
console.log('email sent!');
}
})
};
This is what the array looks like this:
[
[
{
"firstName": "John",
"lastName": "Doe",
"address": "555 Broadway",
"city": "New York",
"email": "john#example.com",
"phone": "2125551212",
"state": {
"code": "NY",
"state": "New York"
},
"timestamp": {
"addedAt": 1443911047642
},
"zip": "10001",
"$id": "-K-jnWa0IBiGCAInbaIr",
}
],
[
{
"item": "Pants",
"description": "Wranglers",
"timestamp": {
"addedAt": 1443911007264
},
"detail": {
"cost": 60,
"size": "36"
},
"$id": "-K-jnMj64LS-XMM18J-8",
},
{
"item": "Pants",
"description": "Levi's",
"timestamp": {
"addedAt": 1443911018026
},
"detail": {
"cost": 80,
"size": "33"
},
"$id": "-K-jnPMJDLJMKIH4rAUe",
}
]
]
I have had same problem....this will solve it.
var cartContent = req.body.slice(1);
//produces new array sans user contact information assuming you pushed it to the front of the array at some point....please do so!
Access properties like this for user contact content
req.body[0].name
For the cart items, it's much easier to loop through or manipulate cartContent sans the UN-releated user contact info object.
cartContent[0].item

Resources