I am making a game in JavaScript. I want to save scores(with names of the players) in Firebase Databse. Here is the structure of my database, but it can be modified if it is needed:
.
How can I get and save to an array i.e. 3 of the best scores and belonging to them names?
Here is part of my code where I am saving the scores and trying to get them:
function writeUserData(name, score) {
firebase.database().ref("scores/").push({
name: name,
score: score,
});
}
var bestScores = {};
var scoresRef = database.ref("scores");
scoresRef.orderByValue().limitToLast(3).on("value", function(snapshot) {
snapshot.forEach(function(data) {
bestScores[data.key] = data.val();
});
});
You're ordering the nodes under scores based on the value of a child property, so in that case you need to use orderByChild and not orderByValue.
var scoresRef = database.ref("scores");
scoresRef.orderByChild("score").limitToLast(3).on("value", function(snapshot) {
snapshot.forEach(function(data) {
console.log(data.key); // "-M-...."
console.log(data.val().name); // "Anrzej"
console.log(data.val().score); // 11
});
});
Related
Building a script in google apps script.
I get values from an invoice data sheet with multiple lines per invoice so as to account for line items.
My progress so far has been to extract individual invoice numbers from the column (each invoice number occurs as many line items the individual invoice has).
The array todaysInvoices looks like this: [35033817, 35033818, 35033819, 35033820, 35033821]
Now, I need a way to create an object for each of these invoice numbers that has different properties (such as invoiceDate and customerName etc.). The initial invoice number as in the array should thereby be assigned as 'id' property to the new invoice object.
I need help to use objects in javascript.
If you require additional information, please let me know.
Below is a screenshot of a simplified version of my order sheet:
This is a clipping of my order sheet. Before and after the shown columns there are many more with more details but the hierarchies of information are already in the image
Below is the code I have so far:
const orderSheet = SpreadsheetApp.openById('SPREADSHEETID').getSheetByName('SHEETNAME');
const invoiceTemplate = DriveApp.getFileById('DOCUMENTID');
const tempFolder = DriveApp.getFolderById('FOLDERID');
const invoiceData = orderSheet.getRange(4,7, orderSheet.getLastRow() - 1, 57).getDisplayValues().filter(function (rows){ return rows[0] === 'INVOICED'});
const invDataRepo = SpreadsheetApp.openById('SPREADSHEETID2');
var timestamp = new Date();
function printBulkInvoices() {
logLineItems ();
var todaysInvoices = uniqueInvIDs ();
todaysInvoices.sort();
todaysInvoices.map(String);
//fetchInvData (todaysInvoices);
Logger.log (todaysInvoices)
}
function fetchInvData (invoiceIDs) {
let invoices = {
}
Logger.log(invoices)
invoiceIDs.forEach
}
function fetchLineItems (invoiceDataArray) {
}
// send array of todays unique invoice numbers (later all inv data?) to invdata sheet and log them
function logTodaysInvoices (invIDArr){
invIDArr.forEach
invDataRepo.getSheetByName('invdata').getRange(invDataRepo.getSheetByName('invdata').getLastRow()+1,1,invIDArr.length,1).setValue(invIDArr);
}
// return an array of unique invoice ids from todays invoice data
function uniqueInvIDs (){
let singleArray = invoiceData.map(row => row[5]);
let unique = [...new Set(singleArray)];
return unique;
}
//log incoicedata to invdatarepo-sheet 'lineitems'
function logLineItems (){
invDataRepo.getSheetByName('lineitems').getRange(invDataRepo.getSheetByName('lineitems').getLastRow()+1,2,invoiceData.length,invoiceData[0].length).setValues(invoiceData);
}
It's hard to say exactly what you need since we cannot see your Invoice Data Sheet.
But here's something that might give you a start:
let iobj = {idA:[]};
[35033817, 35033818, 35033819, 35033820, 35033821].forEach((id => {
if(!iobj.hasOwnProperty(id)) {
iobj[id]={date: invoiceDate, name: customName, items:[]};
iobj.idA.push(id);//I find it handy to have an array of object properties to loop through when I wish to reorganize the data after it's all collected
} else {
iobj[id].items.push({item info properties});//I am guessing here that you may wish to addition additional information about the items which are on the current invoice
}
});
Javascript Object
To follow up from your question:
Your loop to collect object data would start to look something like this:
function getInvoiceData() {
const ss = SpreadsheetApp.getActive();
const ish = ss.getSheetByName('Invoice Data');
const isr = 2;
const hA = ish.getRange(1, 1, 1, ish.getLastColumn()).getValues()[0];
let idx = {};//object return head index into row array based on header title which in this case I assume invoice number is labeled 'Invoicenumber'
hA.forEach((h, i) => {idx[h] = i});
const vs = ish.getRange(isr, 1, ish.getLastRow() - isr + 1, ish.getLastColumn()).getValues();
let iobj = { idA: [] };
vs.forEach(r => {
if (!iobj.hasOwnProperty(r[idx['invoicenumber']])) {
iobj[r[idx['invoicenumber']]] = { date: r[idx['invoicedate']], name: r[idx['customername']], items: [] };
iobj.idA.push(r[idx['invoicenumber']]);
} else {
iobj[r[idx['invoicenumber']]].items.push({ iteminfoproperties:'' });
}
});
}
I have a huge list of items about almost all the crops and these data is to be plotted using maps and charts. I would like to count the number of each crop, say how many times was cabbage planted. I use Firebase database to store the data and I retrieve it using this function below:
database = firebase.database()
var ref = database.ref('Planting-Calendar-Entries');
ref.on('value', gotData, errData);
function gotData(data){
console.log(data.val())
var veggie = data.val();
var keys = Object.keys(veggie);
console.log(keys);
let counter = 0
for (var i = 0; i < keys.length; i++){
var k = keys[i];
var Veg_planted = veggie[k].Veg_planted;
var coordinates = veggie[k].coordinates;
if (Veg_planted == 'Cabbage'){
counter++;
}
// vegAll = Veg_planted.count()
console.log(Veg_planted, coordinates)
}
console.log(counter)
}
function errData(err){
console.log('Error!');
console.log(err)
}
This data I retrieve it from the database where it gets updated whenever someone submits their planting information. The code I used above will only apply if my list is small, but I have a list of about 170 items and it would be hard to write code to count each crop individually using something like let counter = 0, counter++. Is there a way I could navigate around this?
I'm assuming data.val() returns an array, not an object, and you're misusing Object.keys() on an array instead of just looping over the array itself. If that's true, then it sounds like you want to group by the Veg_planted key and count the groupings:
const counts = Object.values(veggie).reduce((counts, { Veg_planted }) => ({
...counts,
[Veg_planted]: (counts[Veg_planted] || 0) + 1
}), {});
Usage:
const veggie = [{ Veg_planted: 'Cabbage' }, { Veg_planted: 'Cabbage' }, { Veg_planted: 'Corn' }];
// result of counts:
// {Cabbage: 2, Corn: 1}
Actually: the code to count the items is probably going to be the same, no matter how many items there are. The thing that is going to be a problem as you scale though is the amount of data that you have to retrieve that you're not displaying to the user.
Firebase does not support aggregation queries, and your approach only works for short lists of items. For a more scalable solution, you should store the actual count itself in the database too.
So:
Have a blaCount property for each bla that exists.
Increment/decrement the counter each time your write/remove a bla to/from the database.
Now you can read only the counters, instead of having to read the individual items.
Firestore would be better option. You can query based on the field value.
var plantingRef = db.collection("PlantingCalendarEntries");
var query = plantingRef.where("Veg_planted", "==", "Cabbage");
if you still want to stuck with realtime database.
Save Counters to database.
Or use cloud dunctions to count.
I am not able to get the email list data from firebase. All it shows is "null".
Although the variable agent0 shows the correct selected data from the array, I can't seem to use it with the firebase reference.
How can I use one of the array values to get data from firebase?
var agent0 = agents[0];
window.alert(agent0);
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins").child(agent0);
refPullEmail.once("value")
.then(function(snapshot) {
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
Database :
To retrieve the EmailList try the following:
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins").child("ALLIANCE");
refPullEmail.once("value")
.then(function(snapshot) {
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
The above will retrieve the EmailList under node ALLIANCE.
If you want to retrieve all the EmailList under node All Origins, then try the following:
var refPullEmail = firebase.database().ref("Forwarder Contact").child("All Origins");
refPullEmail.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot){
var agentEmail_0 = snapshot.child("EmailList").val(); //return list emails
window.alert(agentEmail_0);
});
});
Here, you iterate inside the direct children of All Origins and retrieve the EmailList.
I am trying to check if there are duplicates in a collection. New to stored procedures and azure database, so for now am trying to count distinct entries. If count distinct (column name) = count (column name), there are no duplicates, so I am trying to write a stored procedure for that. But azure retrieves 100 docs at a time only. I need the count over all the batches available.
I was able to get the count of distinct entries, but it shows the count for the first batch retrieved - which is 100. I need the count over all the batches.
function sample(prefix) {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT DISTINCT VALUE r.column FROM root r',
function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
response.setBody(JSON.stringify(feed.length));
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
I expect the output to count the distinct entries in the collection. It should be 103, but the actual is 100 which is the number retrieved by azure at one go.
The default value of FeedOptions pageSize property for queryDocuments is 100, which might be the cause of the issue. Please try to set the value to -1. The following stored procedure works fine on my side, please refer to it.
function getall(){
var context = getContext();
var response = context.getResponse();
var collection = context.getCollection();
var collectionLink = collection.getSelfLink();
var filterQuery = 'SELECT * FROM c';
collection.queryDocuments(collectionLink, filterQuery, {pageSize:-1 },
function(err, documents) {
response.setBody(response.getBody() + JSON.stringify(documents));
}
);
}
Hope it helps.
This is my database.
I'm trying to iterate through each object and print "Name" value to the console.
This is my JS code
var scores = [];
var database = firebase.database();
database.ref().once("value", function(snap){
scores = snap.val();
});
console.log(scores[1].Name);
From my understanding this is what happens.
snap = {rootKey : [array of objects]
scores = snap.val() = [{Name : Babara}, {Name : Josh}, ......]
scores[1] = {Name : Josh}
scores[1].Name = Josh
EDIT
When I try to print whole array I get this.
database.ref().once("value", function (snap) {
scores = snap.val();
console.log(scores);
console.log(scores[1]);
});
As seen here, I can't access objects inside the array.
try
database.ref().once("value", function(snap){
snap.forEach(function(childSnap) {
scores['Name'].push(childSnap.val().Name);
scores['Score'].push(childSnap.val().Score);
});
});