How search users form firebase - javascript

I want search from firstore database user that displayname or nickname contians the search term. I have following code but don't search.
export const searchUsers = async (queryText)=>{
const searchTerm=queryText.toLowerCase();
const usersRef = collection(db, "users");
const users = [];
// Create a query against the collection.
const q = query(usersRef, where("displayName", "array-contains", searchTerm)||where("nickName", "array-contains", searchTerm) ,orderBy("nickName"));
onSnapshot(q, (querySnapshot) => {
querySnapshot.forEach((doc) => { console.log("docsearch:"+doc)
users.push(doc.data());
});
})
return users;
}

I dscoveret that the best way from this issue is make indexes with algolia following the next video: https://www.youtube.com/watch?v=eD1CUWs_3_k&ab_channel=midudev

Related

Why Firebase query with orderByChild returns a link?

According to the docs, I use this code to get the players in ascending order:
const db = getDatabase();
const playersByPoints = query(
ref(db, 'usersPoints'),
orderByChild('points'),
);
But when I console.log(playersByPoints) I get this:
"https://app-name.firebaseio.com/usersPoints"
Here is the database:
Am I missing something?
Thanks!
Your playersByPoints here is a Query object, which when logged returns the string of the linked database reference.
You need to actually invoke the query using either get(q) or onValue(q) to get the data you are looking for.
// one-off
const playersByPointsQuery = query(
ref(db, 'usersPoints'),
orderByChild('points'),
);
const playersByPointsQuerySnapshot = await get(playersByPointsQuery);
const playersByPoints = [];
playersByPointsQuerySnapshot.forEach(childSnapshot => {
playersByPoints.push({
...childSnapshot.val(),
_key: childSnapshot.key
});
});
// todo: do something with playersByPoints
or
// realtime listener
const playersByPointsQuery = query(
ref(db, 'usersPoints'),
orderByChild('points'),
);
const unsubscribe = onValue(
playersByPointsQuery,
{
next: (playersByPointsQuerySnapshot) => {
// new data available
const playersByPoints = [];
playersByPointsQuerySnapshot.forEach(childSnapshot => {
playersByPoints.push({
...childSnapshot.val(),
_key: childSnapshot.key
});
});
// todo: do something with playersByPoints
},
error: (err) => {
// error
// todo: handle
}
}
);

Nested firestore query in react

I have a firestore database with 2 collections: users and products. Users has a 'cart' field (type: array) which stores the uniqueName (field in products) of the products added to cart by a user. I fetched the 'cart' array and now, for each item, I want to fetch the product doc so I can access each product's individual fields.
*currentUserCart stores the elements from the cart array: strings with the unique product name based on which I do the query in fetchProducts().
While fetchUserCart() works, I followed the same logic for fetchProducts() but it doesnt work.
I tried this, but I get the correct products only if I click again wherever on the modal screen
export const Navbarr = ({items}) => {
const [user, error] = useAuthState(auth);
const [cartItems, setCartItems]=React.useState(0);
const [open, setOpen] = React.useState(false);
const [currentUserCart, setCurrentUserCart]=React.useState([]);
const [currentProducts, setCurrentProducts]=React.useState([]);
const handleOpen = () => {
fetchUserCart();
setOpen(true);
fetchProducts();
};
const fetchProducts=async()=>{
const products=[];
currentUserCart.forEach(async(item)=>{
const q = query(collection(db, "products"), where("uniqueName", "==", item));
const doc = await getDocs(q);
const data = doc.docs[0].data();
setCurrentProducts(currentProducts=>[...currentProducts, data]);
})
console.log(currentProducts);
}
const fetchUserCart = async() =>{
const q = query(collection(db, "users"), where("uid", "==", user?.uid));
const doc = await getDocs(q);
const data = doc.docs[0].data();
setCurrentUserCart(data.cart);
console.log('cart '+currentUserCart);
}
const handleClose = () => setOpen(false);
const fetchUserCartItems=async()=>{
const q = query(collection(db, "users"), where("uid", "==", user?.uid));
const doc = await getDocs(q);
const data = doc.docs[0].data();
let cartItemsClone=data.cartItems;
setCartItems(cartItemsClone);
}
React.useEffect(() => {
fetchUserCartItems();
fetchUserCart();
fetchProducts();
}, [user], [currentUserCart], [currentProducts]);

is there a way to get around using 'await' here?

I am trying to get all the documents in a subcollection by following the firebase documentation, however the error 'await is an reserved identifier' appears.
This is my code currently and I do not see where 'async' could be used with await and the documentation does not indicate that it would be used.
getAuth().onAuthStateChanged((user) => {
if (user) {
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
//reference to the subcollection of subjects in the user's document
const subjectRef = collection(db, "users", auth.currentUser.uid, "subjects");
const querySnapshot = await getDocs(subjectRef);
querySnapshot.forEach((doc) => {
console.log(doc.id, "=>", doc.data());
});
}
});
I have tried getting all the documents with db.collection.('users').document(auth.currentUser.uid).collection('subjects').get() where db = getFirestore(app), however this does not work as the error
'db.collection is not a function' appears and any soloutions I have found to it are not relevant as db is refering firestore not the real time database.
You need to make the callback async:
getAuth().onAuthStateChanged(async (user) => {
if (user) {
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
//reference to the subcollection of subjects in the user's document
const subjectRef = collection(db, "users", auth.currentUser.uid, "subjects");
const querySnapshot = await getDocs(subjectRef);
querySnapshot.forEach((doc) => {
console.log(doc.id, "=>", doc.data());
});
}
});

Firebase User Authentication

Below is my working GET API, however it is using admin.firestore.
As I am a new programmer, I am having difficulties incorporating the Authentication portion
app.get("/", async (req, res) => {
const snapshot = await admin.firestore().collection("users").get();
let user = [{records:[]}];
snapshot.forEach((doc) => {
let id = doc.id;
let data = doc.data();
users.records.push({ id, ...data });
});
res.status(200).send(JSON.stringify(users));
});
What I hope to achieve is that users can only access their own database hopefully something like this
app.get("/", async (req, res) => {
const snapshot = await [user uid's reference].collection([grab user's uid and insert here]).get();
let [insert user's uid here] = [{records:[]}];
snapshot.forEach((doc) => {
let id = doc.id;
let data = doc.data();
[insert user's uid here].records.push({ id, ...data });
});
res.status(200).send(JSON.stringify([insert user's uid here]));
});
The user is not an object but an array, so you cannot use user.records:
// This is invalid
let users = [{records:[]}];
console.log(users.records)
// This is valid
let users = {records: []}
console.log(users.records) // []
You can directly use map() on the QuerySnapshot:
app.get("/", async (req, res) => {
// Get a QuerySnapshot of users collection
const snapshot = await admin.firestore().collection("users").get();
// Map an array containing user data
const users = snapshot.docs.map(d => ({id: d.id, ...d.data()}))
// return the response
return res.status(200).send(JSON.stringify(users));
});

how to get the unique id in firebase

ive had a lot of trouble with firebase arrays, im now using push
I have this
I want to pull all the users down so I do this:
export const pullFromFirebase = () => {
return firebase
.database()
.ref("/users/")
.once("value")
.then(snapshot => {
var users = [];
snapshot.forEach(user => {
users.push(user.val());
});
return users;
});
};
this is fine
however, I now need the unique id -LI7d_i_BmrXktzMoe4p that firebase generated for me so that I can access this record (i.e. for updating and deleting) how do i do this?
You can get the key of the snapshot with the key property: https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#key
So you could change your code to this:
export const pullFromFirebase = () => {
return firebase
.database()
.ref("/users/")
.once("value")
.then(snapshot => {
var users = [];
snapshot.forEach(user => {
let userObj = user.val();
userObj.id= user.key;
users.push(userObj);
});
return users;
});
};
You can change this part:
snapshot.forEach(user => {
users.push(user.val());
});
To instead be:
let usersObj = snapshot.val()
for (var user_id in usersObj) {
users.push(Object.assign(usersObj[user_id], {
user_id: user_id,
});
});
That way, instead of each element in the users array only having email, name and username fields, it has user_id as well.

Categories