Trying to display single user - node.js

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>
);
}

Related

append data to an existing Json file in nodejs

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);

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?

React Native : iterate and display nested objects using Hooks

I want to display my user data stored in my api's
How can I iterate through my apis data.
Can anyone demonstrate it with example ?
My api data looks like this:
{
"data": {
"__v": 0,
"_id": "5edaa8cc76d6b20017",
"createdAt": "2020-06-05T20:19:24.365Z",
"email": "joe#gmail.com",
"name": "Joe",
"role": "user"
},
"success": true
}
Here is the example of my code:
const HomeScreen = props => {
const [dataSource, setDatasource] = useState({});
const Boiler = async () => {
const token = await AsyncStorage.getItem('token');
fetch('{{URL}}/api/v1/auth/me', {
method: 'GET',
headers: new Headers({
Authorization: 'Bearer ' + token,
}),
})
.then(res => res.json())
.then(responeJson => {
console.log(responeJson);
setDatasource({
...dataSource,
dataSource: responeJson,
});
})
.catch(error => {
console.error(error);
});
};
useEffect(() => {
Boiler();
}, []);
}
You response from the API is an object which you can directly render in your component without the need for iteration
Also note that when you update state, you would not explicitly set key as dataSource
Update your state like
setDatasource({
...dataSource,
...responeJson.data,
});
and then render your data like
return (
<View>
<Text>CreatedAt: {dataSource.createdAt}</Text>
<Text>email: {dataSource.email}</Text>
<Text>name: {dataSource.name}</Text>
<Text>role: {dataSource.role}</Text>
</View>
)
If you need to iterate over object use can use for..in loop.
const response = {
"data": {
"__v": 0,
"_id": "5edaa8cc76d6b20017",
"createdAt": "2020-06-05T20:19:24.365Z",
"email": "joe#gmail.com",
"name": "Joe",
"role": "user"
},
"success": true
};
function iterateOverData(data) {
for(let key in data) {
console.log(key, data[key]);
}
}
iterateOverData(response.data);

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")

Find data of those where referenced object id equals to user._id

I am getting all the order details
For example:(example of one order)
{
"customer": {
"id": "5db6ac89d85a2c1c709a42da",
"name": "Testing"
},
"product": {
"id": "5dba78427af9e73b18bdbb22",
"name": "image",
"seller": "Testing",
"price": 100,
"imgurl": "ok"
},
"_id": "5dba788fdeb78931f8a30105",
"quantity": 3
}
When I use find() I get all the elements but I only want to show the data of the one who is logged in
i.e where customer.id equals to req.user._id
I am using find() as shown in the code below:
router.get('/cart',verifyToken, async (req, res)=>{
const order = await Order.find({/* what should be the query here to get the desired result*/},'product , quantity , customer ');
try{
res.send(order)
}catch(err){
res.status(400).send(err);
}});
Any other methods to achieve this
You have to use findOne().Like below
const order = await Order.findOne({'customer.id':req.user._id}) // probably req.body.user._id
or
await Order.findOne( { customer: { id:req.user._id } } )
See the docs here

Resources