how to sort and limit firebase realtime db v9? - javascript

devs.
I am trying to make a table that will show the top scorers.
I am new to firebase v9.
problem:
I am using realtime DB for storing the name and scores of users with doc names and names are same.
as I used orderbyValue, orderbykey and orderbyChild. snapshot.val() returns an object which contains objects ( check at the bottom ) which is unordered and don't know how to access all or loop.
for limiting, I tried limitToLast which works fine but sorting doesn't.
help me to sort and limit this.
this is how my data is stored in realtime database
this is my code to fetch and try to sort
import { getDatabase, ref, set, onValue, query, orderByChild, limitToLast, equalTo, orderByValue, orderByKey } from "https://www.gstatic.com/firebasejs/9.4.1/firebase-database.js";
var namelist = $('.person');
var list = $('.scores');
// const scoreBoardRef = ref(db, 'users');
const scoreBoardRef = query(ref(db, 'users'), orderByChild('score'));
onValue(scoreBoardRef, (snapshot) => {
const data = snapshot.val();
console.log(data); // this returns object containing object and **i don't know how to deal with this.**
//console.log(scoreBoardRef);
list[0].textContent = data.score; // here i want score
namelist[0].textContent = "";//here i want name
//my main goal is to loop through top 3 or 10 data and print it to table
});
In the console, this is what I get
⬇{abcd: {…}, man2: {…}, nacho: {…}, two: {…}}
▶abcd: {name: 'abcd', score: 15}
▶man2: {name: 'man2', score: 20}
▶nacho: {name: 'nacho', score: 21}
▶two: {name: 'two', score: 18}
▶[[Prototype]]: Object

As Dharmaraj commented: the results in the snapshot are actually ordered, but when you call snapshot.val() it gets converted to a JSON object and the keys in a JSON object are by definition not ordered.
To get the results in order, loop over them with snapshot.forEach:
onValue(scoreBoardRef, (snapshot) => {
snapshot.forEach((child) => {
const data = child.val();
console.log(data);
});

Related

Array Spread Syntax not working as expected on React State Variable

Hi I'm trying to take some data from my Firebase Firestore and save it to state in my React app. My code is this:
const [firebaseOrders, setFirebaseOrders] = useState([])
useEffect(() => {
const getOrders = async () => {
const querySnapshot = await getDocs(collection(db, `users/carlos#example.com/orders`));
querySnapshot.forEach((doc) => {
const newOrder = doc.data()
setFirebaseOrders([...firebaseOrders, newOrder])
})
}
getOrders();
}, [])
console.log(firebaseOrders)
I am expecting to get an array of objects with my orders. Instead my array is not saving when I use the spread operator so I end up with just the last item in my array:
Here's a pic of what I get in the console
[{…}]
->0 : {titles: Array(2), timestamp: nt, prices: Array(2), amount: 869.99, amount_shipping: 6.99, …}
length : 1
->[[Prototype]] : Array(0)
[{…}]
->0 : {amount: 78.29, timestamp: nt, titles: Array(2), amount_shipping: 0, prices: Array(2), …}
length : 1
->[[Prototype]] : Array(0)
I feel like I am missing something basic, can anyone help me out?
Modifying state is an asynchronous operation, so doing this in a tight loop (as you do) means that you're overwriting the previous value each time.
Instead, call setFirebaseOrders just once with all results:
setFirebaseOrders(
querySnapshot.docs.map((doc) => doc.data());
})
Also note that the console.log(firebaseOrders) may not show the correct value, as it likely runs before setFirebaseOrders(...) has run/completed.
If you want to see the orders from the state, show them in components in your UI. If you want to console.log what you get from the database, do so in the callback:
const orders = querySnapshot.docs.map((doc) => doc.data());
console.log(orders);
setFirebaseOrders(orders);

How can I add objects to an array of Objects which has same keys in firestore?

I have a Collection called Notes which has a document that is an UID of the user that consists of collection of an Array of objects which look something like this
obj {[
{title:"Note 1",desc:"description 1"},
{title:"Note 2",desc:"description 2"},
{title:"Note 3",desc:"description 3"},
]}
this is the actual Firestore collection where is now allowing me to store objects with the same key using the code I wrote but If I'm trying to add it manually then I
I'm using React with Firebase and using Firestore as a database
the problem I'm facing is that if I add more objects to the array mentioned above with the same key it's not creating a duplicate Firestore is not letting me add more objects with the same key. Other than that it is running just fine.
Below is the code for adding a new Notes Collection
// this function create a new Notes Collection
const createNotes = async (title, description) => {
const uid = auth.currentUser.uid; // For document name
const notesRef = doc(db, "Notes", uid);
const data = {
note: [{ title: title, description: description }],
};
try {
await setDoc(notesRef, data);
} catch (error) {
console.log(error);
}
};
Below is the code for updating the array of objects, this was the only way I could find to add multiple objects into an array on firestore
const updateNotes = async (title, description) => {
const uid = auth.currentUser.uid;
const notesRef = doc(db, "Notes", uid);
const data = {
note: arrayUnion({ title: title, description: description }),
};
try {
await updateDoc(notesRef, data, { merge: true });
} catch (error) {
console.log(error);
}
};
Is there a solution to this?
According to your last comment:
If suppose I have added an array field such as {title:”a”,desc:”b”} in the array and if again try to add the same object it will not create a duplicate of the same object how will I be able to have multiple same objects in an array?
Please note that you cannot add duplicate elements in an array using arrayUnion. According to the official documentation:
arrayUnion() adds elements to an array but only elements not already present.
So if you need to have duplicate elements, then the single option that you is to read the document, add the duplicate element in the array, and then write the document back to Firestore.

How to combine the received data in a state?

When I execute an API request, I get a lot of objects that are not connected by a common array. I'm trying to combine them into one state, but only one value is stored. How can I store all the received objects in the general array of my state? Everything would be fine, but I need the array to be stored in the state, in which all objects from the API will lie, in order to transfer this array to Redax
const [planets, setPlanets] = useState([]);
useEffect(() => {
(async () => {
const users = await axios(world);
const worldData = users.data;
setPlanets(worldData);
})();
}, [nextTeam, world]);
and i take get data
I am trying to transfer all these objects to state planets, but objects are transferred there individually. Not creating an array.
This is a screenshot of console.log(planets)
You can use Object.keys
let planets = {
tatooine:{
population: "1,3M", type: "desert"
},
coruscant:{
population: "130B", type: "city"
},
}
let array = []
Object.keys(planets).forEach(planet => array.push({
name: planet,
...planets[planet]
}))
console.log(array)

How can I store and filter large JSON objects (above 70,000)?

const users = [
{id:1, email:"abc#email.com"},
{id:2, email:"xyz#email.com"},
{....}(~70,000 objects)
]
function a(){
const id = 545
users.filter((value)=>{
if(value.id === id)
return true
})
}
We have 70,000 users' objects. we need to filter the email based on the id.
users= [{id: '1001', email: "abc#gmail.com"}, {{id: '1002', email: "spc#gmail.com"} , ..];
Using array and array.filter() ends up in the error.
Error
what's the best way of approach for this?
It might be best to convert your array into a Map so that lookups can be made without scanning the entire array. As such:
const lookupMap = new Map(users.map((u) => [u.id, u]));
so now you can
const user = lookupMap.get(userId)
without having to scan all 70000 user objects.

How to iterate through a string array, creating an object per item?

I have the following model:
const mongoose = require('mongoose');
const schema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
Name: String,
Author: String,
Library: String,
}, { collection: 'Books' });
module.exports = mongoose.model('Books', schema);
I have an array containing book titles strings (bookTitles). I want to iterate through that list and for each title, create a new Book object. I plan to save that in a list so I may do an insertMany to Mongo. I plan to do this as follows:
const Books = require('../models/Books');
const booksToAdd = [];
bookTitles.forEach(bookTitle => booksToAdd.push(new Books({
Title: bookTitle
})))
console.log(booksToAdd);
await Books.insertMany(booksToAdd);
I have properly set up mongoose locally and am able access the db with other services in this project. Currently, if I print the books array I get an undefined object which has me thinking I'm not properly adding the Book object to the books array. In which case adding to the Books collection wouldn't work anyways since I'm not actually adding anything. How should I be iterating through the bookTitles so to create an array of Books objects, which would be added to the mongo collection with insertMany?
Looks to me like you are almost there, i have no clue of mongo.
const Books = require('../models/Books');
const booksToAdd = [];
bookTitles.forEach(bookTitle => booksToAdd.push(new Books({
Title: bookTitle
})))
The one thing i am not sure of is why you are using booksToAdd.push(new Books
What makes sense to me is booksToAdd.push(new Object //works for my example data
const booksToAdd = [];
let bookTitles = ["first","second","third"];
bookTitles.forEach(bookTitle => booksToAdd.push(new Object({
Title: bookTitle})))
//booksToAdd
// (3) [{…}, {…}, {…}]
0: {Title: "first"}1: {Title: "second"}2: {Title: "third"}length: 3__proto__: Array(0)
We cannot see any part of the code where you initialize the bookTitles property.
If there isn't, there isn't any iteration also. Provide us with more code.
Also try to put a console.log(bookTitles) before its forEach.

Categories