NEXT.JS , fetching single product from mongo db, - javascript

I have data in mogno db, all data are fetched , when I click to individual item, I want to display details of item.
On url I can see how _id is changed, I am getting different _id, but console.log(product) show me still same product detail.
It is fetching still same product.
what am I doing wrong?
function to find individual product:
export async function getServerSideProps(context) {
const { id } = context.query
await db.connect()
const product = await Product.findOne({ id }).lean()
await db.disconnect()
return {
props: {product: product ? db.convertDocToObj(product) : null}
}
}
then show product
const ProductDetail = ({ product }) => {
console.log(product) // I am getting still same product {_id: '63e19a054765...',
...

Related

How to query documents from an array in firebase JS

and thanks in advance if anyone can help with this.
I am attempting to fetch all the posts that a user is following.
I store who a user is following in an array like so: [uid, uid, uid, ...]
step 1: get who a user is following
step 2: get the posts of the users in the user the following array
i.e. get the posts of all these people -> [uid, uid, uid, ...]
issue: after step 2 I recieve [user1posts],[user2posts],[user3posts], ......
the 'posts' will actually flicker all the user's posts in order and then display the last user in the array's posts permanently.
desired: after step 2 I would receive [ user1posts, user2posts, user3posts, ... ]
so:
currently = posts: [user1posts],[user2posts],[user3posts], ......
desired = posts: [ user1posts, user2posts, user3posts, ... ]
const [posts, setPosts] = useState([]);
const [refreshing, setRefreshing] = useState(false)
useEffect(() => {
function fetchUserFollowing(){
firebase.firestore()
.collection('users')
.doc(firebase.auth().currentUser.uid)
.onSnapshot((snapshot) => {
let following = snapshot.data().following
for(let i = 0; i < following.length; i++)
fetchUsersFollowingPosts(following[i])
})
}
function fetchUsersFollowingPosts(uid){
firebase.firestorm()
.collection('posts')
.doc(uid)
.collection('todaysPosts')
.orderBy('createdAt','desc')
.onSnapshot((snapshot) => {
let posts = snapshot.docs.map(doc =>{
const data = doc.data()
const id = doc.id;
return({id, ...data})
})
setPosts([...posts])
})
}
fetchUserFollowing()
}, [props.currentUser && props.currentUser.following])
recap: this returns a separate array for each user. I've been attempting to get all the arrays into one single array. I'm sure it's an easy fix, however, I cannot figure this out for the life of me.
thanks again
I have tried lots of workarounds

How to get nested key in firebase real time database

I am creating a database for the products. The products are pushed into the database successfully but I am facing a problem in getting the data because the keys are nested. How can I target the nested key?
Please help me.
Using the below code I am getting my all the products data of currently logged in user.
useEffect(() => {
const getProductsData = async () => {
const userId = await AsyncStorage.getItem('uid')
database()
.ref(`Products/${userId}`)
.on('value', data => {
console.log(data.val())
});
}
getProductsData()
}, [])
console of the data.val()
Assuming that your userId is the dUD7M... value in the screenshot you shared, the data snapshot you get will contain the data for both child nodes in that screenshot. You can loop over those children with:
const userId = await AsyncStorage.getItem('uid')
database()
.ref(`Products/${userId}`)
.on('value', snapshot => {
snapshot.forEach((data) => { // 👈
console.log(data.val())
});
});

array.prototype..forEach function skipped with values in variable

I have a problem, i have a Firebase Firestore Database connected to my React.JS Project, where users can enroll to courses. Now if i'm trying to load the users collection from the DB it returns 1 entry.
const fetchAthletes = async () => {
debugger
try {
const athletes: Array<any> = [];
const athleteRef = collection(db, COLLECTION_NAME_ATHLETE);
const getAthleteQuery = query(athleteRef, where('user', '==', userAuthToken.accessToken));
const querySnapshot = await getDocs(getAthleteQuery)
if (querySnapshot.docs) {
//this for each gets skipped, even when querySnapshot.doc has values in it
querySnapshot.forEach((doc) => {
athletes.push({
id: doc.id,
...doc.data()
});
setAthletes(athletes as Array<Athlete>);
})
}
} catch (error: unknown) {
enqueueSnackbar((error as string), { variant: 'error', autoHideDuration: 3000 })
}
}
But when i want to loop over it via array.prototype.map it always skips it.
I debbuged through the funtion and found out that docs from Firestore is set with values tbat i wanna recieve.
Data returned by Firestore
I have no clue why it doesn't work. Any idea or help is appreciated
Rather than attempt to individually set each doc into state, build up your array and set the entire thing into state
const querySnapshot = await getDocs(getAthleteQuery);
setAthletes(querySnapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));

Mongoose Update Field With the Item of the Another Field That is Array

I am building an Expense Tracker Application, There is a User Collection that has fields like Name, Amount, Expenses Array, Incomes Array, and So On.
My Database Is Mongo Db with Mongoose and the Server Is Written In Express.
Here Is A Screenshot Of the Database after The Values are Filled
I am trying to Implement a Route in which The User Can Delete an Expense and After Deleting the Expense I want to update the Balance and make the Balance = Balance + Expense. I am able to Delete and Expense But Not able to Update the Balance as I do not know how to retrieve the Balance from the Deleted Expense
Here is the Delete Route :
router.delete("/", (req, res) => {
const { UserID, ExpenseID } = req.query;
const query = {
$pull: {
Expenses: { _id: ExpenseID },
},
};
User.findByIdAndUpdate(UserID, query)
});
I want to add a Mongoose Method which Will Fetch the Expense Amount from the Received Expense Id and Store it in a variable and After the Expense Gets Deleted, I want to call a method to update the balance of the User in the Promise.
Here is an example of what I intend to do
// Deletes An Expense
router.delete("/", (req, res) => {
const { UserID, ExpenseID } = req.query;
const query = {
$pull: {
Expenses: { _id: ExpenseID },
},
};
User.find({/*Some Query Which Will Return me The Provided Expense ID's Amount*/})
User.findByIdAndUpdate(UserID, query)
.then(() => {
// Once I find and Remove the Expense, Now I would Like to Update the Users Balance
// NewBalance = OldBalance + Expense ID's Amount Returned by the Find Method
// Here I would Call another User.find method to update the Users Balance
})
});
Let's Say From the Above Database Snap, I want to delete the Expenses (Starting From 0) 1st Object Element, Name: Uber Fare, I will send the Object Id which is 6091f725403c2e1b8c18dda3 to the Server and should Expect my Balance to Increase from 48495 to 49695
What you can do is:
Fetch user document with UserID
Find the expense with ExpenseID
Update the Balance with the expense amount
Remove expense from Expenses array
Save user document
router.put("/", async (req, res) => {
try {
const { UserID, ExpenseID } = req.query;
let user = await User.find({ _id: UserID });
index = user.Expenses.findIndex((expense) => expense._id === ExpenseID);
if (index != -1) {
user.Balance += user.Expenses[index].Amount;
user.Expenses.splice(index, 1);
}
await user.save();
return res.status(200).json({ success: true, user: user });
} catch (error) {
return res.status(400).json({ success: false, error: error })
}
});
NOTE: Since this is updating the document, I configured put method instead of delete on the router.
Create a static method for the schema like so
userSchema.statics.deleteExpenseUpdateBalance = async function (userID, expenseID) {
const user = await this.findOne({ _id: userID });
let userExpenses = user.Expenses;
userExpenses.forEach((expense) => {
if (expense._id === expenseID) {
let amount = expense.Amount;
let index = userExpenses.indexOf(expense);
userExpenses.splice(index, 1);
user.Balance += amount;
return;
}
});
user.save((err) => {
if (err) {
console.log(err)
}
});
};
Access this in your route handler
router.delete("/", async (req, res) => {
const { UserID, ExpenseID } = req.query;
let result = await User.deleteExpenseUpdateBalance(UserID, ExpenseID)
});
This static method will remove the expense and update the balance.
Explanation: The static method just finds the user and iterates through their Expenses and removes the required expense and the amount is just added to the balance. Finally the user.save() method is called to save all documents.
NOTE: Use this only if you are sure that the expenseID exists in the Expense array, otherwise you'll just have to add an extra check for that in the static method
Also put the static method in the file where you create your schema and model in between both of their creations i.e after you've created the userSchema and before you finalise it into a model.

How do I created a nested database in Firebase through a React action creator?

I want to add an object, instead of a single field, to my Firebase data through an action creator. The database will have a nested structure like the following:
Item:
Name
Description
Booking info
Booking date
Renter name
Following is my action creator:
export const book = bookingDate => {
return (dispatch, getState, {getFirebase, getFirestore}) => {
const firebase = getFirebase();
const firestore = getFirestore();
const profile = getState().firebase.profile;
const userId = getState().firebase.auth.uid;
firestore.collection('items').doc(bookingDate.itemId).set({
booking: {...bookingDate,
renterFirstname: profile.firstName,
renterLastname: profile.lastName,
renterId: userId,
createdAt: new Date()
}
}).then(() => {
dispatch({ type: BOOKING_SUCCESS });
}).catch( err => {
dispatch({ type: BOOKING_ERROR }, err);
});
}
}
The set() method replaces the existing information with the new data, which isn't what I want. I tried the add() method, but I'm not sure how to retrieve the existing data at the same time so that I can use the spread operator.

Categories