Filter Firebase query with javascript - javascript

The JSON of my firebase database looks like this:
{
"Films" :
[
{
"Title" : "Rear Window",
"Actors" : [ "James Stewart", "Grace Kelly", "Raymond Burr" ],
"Year" : "1954",
"Writer" : [ "John Michael Hayes (screenplay)", "Cornell Woolrich (short story)" ]
},
{
"Title" : "The Ring",
"Actors" : [ "Carl Brisson", "Lillian Hall-Davis", "Ian Hunter" ],
"Year" : "1927",
"Writer" : [ "Alred Hitchcock" ]
},
{
"Title" : "The Farmer's Wife",
"Actors" : [ "Jameson Thomas", "Lillian Hall-Davis", "Gordon Harker" ],
"Year" : "1928",
"Writer" : [ "1928" ]
}
]
}
I am building out my html based on the initial query from firebase like so:
// Initialize FireBase Database
firebase.initializeApp(config);
// Query the root of FireBase
var query = firebase.database().ref();
// Get a snapshot of all of the data
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var childData = childSnapshot.val();
buildFilms(childData);
});
});
// Build out the films
function buildFilms(films) {
for ( i = 0; i < films.length; i ++ ) {
var numOfActors = films[i].Actors.length,
filmDiv = document.createElement('div'),
filmTitle = document.createElement('h1');
filmTitle.innerHTML = films[i].Title;
filmDiv.setAttribute("id", "film" + i);
filmDiv.setAttribute("class", "film");
document.getElementById("wrapper").appendChild(filmDiv);
document.getElementById("film" + i).appendChild(filmTitle);
listActors(films, numOfActors);
showYear(films);
}
}
// List out Actors per film
function listActors(films, numOfActors) {
for ( subindex = 0; subindex < numOfActors; subindex ++ ) {
var actorTitle = document.createElement('h2');
actorTitle.innerHTML = films[i].Actors[subindex];
document.getElementById("film" + i).appendChild(actorTitle);
}
}
// List years per film
function showYear(films) {
var yearSpan = document.createElement('h4');
yearSpan.innerHTML = films[i].Year;
document.getElementById("film" + i).appendChild(yearSpan);
}
I would then like to use a basic html text input to repaint the dom on submit using Firebase's built in query, so something like this:
function runSearch(e) {
e.preventDefault();
var title = $('#title').val().toLowerCase();
$("#wrapper").empty();
setTimeout(function() {
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
// Need to narrow the films to the matching search input here
buildFilms(newFilteredData);
});
});
}, 1000)
}
I cannot figure out how to use the input to query my firebase data by "Title". Any help is much appreciated.

I hope firebase query orderBy startAt endAt will solve your requirement.
Note: This wont help you if you try to orderBy multiple fields, you'll have to write some other logic to achieve multiple fields orderBy.
Try the below code snippet. It'll filter the data for you!!
Hope this helps you!
var title = 'movie';
query
.orderByValue()
.startAt(title).endAt(title)
.on('value', function(snapshot) {
var movie = snapshot.val();
//do whatever you want.
});
For complete information on the Query related, please visit the below link
https://firebase.google.com/docs/reference/js/firebase.database.Query

This should work:
// Get the root of FireBase
var root = firebase.database().ref();
// Query the Films node under it
var query = root.child("Films");
// Get a snapshot containing the matching children from under Films
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val().Title);
});
});

Related

JavaScript - Targeting an object value to create another variable

So I have an array which looks like this:
[
{ TransactionValues: '50.00' },
{ TransactionValues: '-77.43' },
{ TransactionValues: '-20.23' },
{ TransactionValues: '200.23' }
]
I am trying to find a way to target the monetary value and create a variable based on the sum of these. When I try to target the "50.00" for example I get "Undefined" and it's still an array.
I'm not exactly sure how I can target it specifically, is it possible? Any help would be appreciated
As per the comments here is the full code (be wary I'm still learning so it's not elegant):
var fs = require('fs');
var parse = require('csv-parse');
var transactionValues = []; //Need an array to hold transactions
var currentTrans = [];
var savingsTrans = [];
//constuctor for transactions
function addData (id, accountType, initiatorType, dateTime, transactions) {
var data = {
"AccountID" : id,
"AccountType" : accountType,
"InitiatorType" : initiatorType,
"DateTime" : dateTime,
"TransactionValues" : transactions
}
transactionValues.push(data); //should add a new line
}
function logTrans (accountType, transactions) {
if (accountType == "CURRENT") {
var cTrans = {
"TransactionValues" : transactions
}
currentTrans.push(cTrans);
}
else {
var sTrans = {
"TransactionValues" : transactions
}
savingsTrans.push(sTrans);
}
};
//parses the csv file, loops each row and adds it to the transactionValue array
var parser = parse({columns: true}, function (err, results) {
console.table(results);
for (const row of results) {
addData(row.AccountID, row.AccountType, row.InitiatorType, row.DateTime, row.TransactionValue );
logTrans(row.AccountType, row.TransactionValue);
}
console.log(transactionValues);
console.log(currentTrans);
console.log(savingsTrans);
});
fs.createReadStream(__dirname+'/testData/customer-1234567-ledger.csv').pipe(parser)
not completely following but at the end of the day you have an array like data below.
you can use filter to target the attribute you want.
you can use map to pull out just the values.
you can use reduce to sum them all up.
run the snippet below to see each step
const data = [
{ TransactionValues: '50.00', AccountType: 'CURRENT' },
{ TransactionValues: '-77.43', AccountType: null},
{ TransactionValues: '-20.23', AccountType: 'CURRENT' },
{ TransactionValues: '200.23', AccountType: null }
];
const CurrentTrans = data.filter((x) => x.AccountType === 'CURRENT');
const SavingTrans = data.filter((x) => x.AccountType !== 'CURRENT');
console.log('CurrentTrans');
console.log(CurrentTrans);
console.log('SavingTrans');
console.log(SavingTrans);
const CurrentTransValues = CurrentTrans.map((x) => parseFloat(x.TransactionValues));
const SavingTransValues = SavingTrans.map((x) => parseFloat(x.TransactionValues));
console.log('CurrentTransValues');
console.log(CurrentTransValues);
console.log('SavingTransValues');
console.log(SavingTransValues);
const TotalCurrentValues = CurrentTransValues.reduce((sum, x) => sum + x);
const TotalSavingValues = SavingTransValues.reduce((sum, x) => sum + x);
console.log('TotalCurrentValues');
console.log(TotalCurrentValues.toFixed(2));
console.log('TotalSavingValues');
console.log(TotalSavingValues.toFixed(2));
So I may have fixed it by using parseFloat in my addData and logTrans functions:
function addData (id, accountType, initiatorType, dateTime, transactions) {
var data = {
"AccountID" : id,
"AccountType" : accountType,
"InitiatorType" : initiatorType,
"DateTime" : dateTime,
"TransactionValues" : parseFloat(transactions)
}
transactionValues.push(data); //should add a new line
}
function logTrans (accountType, transactions) {
if (accountType == "CURRENT") {
var cTrans = parseFloat(transactions);
currentTrans.push(cTrans);
}
else {
var sTrans = parseFloat(transactions);
savingsTrans.push(sTrans);
}
};
Now that seems to of worked. So I can use the "Sum values of objects in array" as suggested before. Thank you everyone :)

How to intersection query Real-time Firebase database?

I'm trying to gain an understanding of query in Firebase. I want to pass userId A & B and find out if they are subscribed to a common chatId, it will either return true or false.
How can query both userId and evaluate results for my desired output?
export const checkForExistingChat = (currentUserId, recipient) => {
var IdList = {}
var query = database
.ref(`Chats/${currentUserId}`)
.orderByChild("subscribedToChat")
.once("value", function (dataSnapshot) {
dataSnapshot.forEach(function (childSnapshot) {
const childData = childSnapshot.val();
console.log("childData : ", childData);
});
});
};
Export JSON of Chat
"Chats" : {
"61vtPjp8YVVSzpvexwXMgEHghYf1" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"2d718ea7-eafa-48db-af14-f165f07b3b08" : "2d718ea7-eafa-48db-af14-f165f07b3b08",
"2e4fd8bb-4afb-4229-83ec-5a427fe2731d" : "2e4fd8bb-4afb-4229-83ec-5a427fe2731d",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118",
"3a816ac1-6e97-4d66-ae19-77e65f8c2df4" : "3a816ac1-6e97-4d66-ae19-77e65f8c2df4",
}
},
"qqpBNbEa8ZSiCEUlseFeGeiRqzh2" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118"
}
}
}
Since you already know how to load data from Firebase, this is essentially a non-Firebase problem: finding the overlapping keys in two lists of keys.
A quick code snippet:
var json = {
"Chats" : {
"61vtPjp8YVVSzpvexwXMgEHghYf1" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"2d718ea7-eafa-48db-af14-f165f07b3b08" : "2d718ea7-eafa-48db-af14-f165f07b3b08",
"2e4fd8bb-4afb-4229-83ec-5a427fe2731d" : "2e4fd8bb-4afb-4229-83ec-5a427fe2731d",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118",
"3a816ac1-6e97-4d66-ae19-77e65f8c2df4" : "3a816ac1-6e97-4d66-ae19-77e65f8c2df4",
}
},
"qqpBNbEa8ZSiCEUlseFeGeiRqzh2" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118"
}
}
}
};
var keys1 = Object.keys(json.Chats["61vtPjp8YVVSzpvexwXMgEHghYf1"].subscribedToChat);
var keys2 = Object.keys(json.Chats["qqpBNbEa8ZSiCEUlseFeGeiRqzh2"].subscribedToChat);
console.log(keys1, keys2);
var commonKeys = keys1.filter(function(key) {
return keys2.indexOf(key) >= 0;
});
console.log(commonKeys);
This is an O(n^2) algorithm, but I doubt that'll be a concern on the list sizes you're likely to have. If it is a concern, and the lists are sorted, you can keep a cursor in each least, and move forward only through them once to make it an O(2n) algorithm.

Trouble filtering data in firebase database

I'm trying to filter some data from firebase database in a cloud function.
That data looks like this :
"items": {
"id1": {
"status": {
"creation": timestampValue,
"status": "initialized"
},
"data" : data1
}
"id2": {
"status": {
"status": "loaded"
},
"data" : data2
},
"id2": {
"status": {
"creation": timestampValue,
"status": "loaded"
},
"data" : data
},
"id3": {
"status": {
"creation": timestampValue,
"status": "ended"
},
"data" : data3
}
}
I want to use a filter based on the creation field.
The field is not always present.
My code is inspired by this one :
https://github.com/firebase/functions-samples/blob/master/delete-old-child-nodes/functions/index.js
here's the code I wrote :
const CUT_OFF_TIME = 24 * 60 * 60 * 1000; // 24 Hours in milliseconds.
exports.cleanAfter24h = functions.database.ref('/items/{itemId}').onUpdate((change, event) => {
const ref = change.after.ref.parent; // reference to the parent
const now = Date.now();
const cutoff = now - CUT_OFF_TIME;
const oldItemsQuery = ref.orderByChild('creation').endAt(cutoff);
return oldItemsQuery.once('value').then((snapshot) => {
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
let childData = child.val();
if (childData.status.creation) {
let elapsed = childData.status.creation - cutoff;
if (elapsed <= 0) {
updates[child.key] = null;
}
} else {
console.log(child.key + ' does not have a creation date');
}
});
// execute all updates in one go and return the result to end the function
return ref.update(updates);
});
});
When the code is run, all items are retrieved, even those that have a timestamp smaller than the cutoff and those that do not have a creation field.
Any suggestions how to fix that?
I tried removing the items that have no creation field by adding a startAt("") before the endAt as suggested here :
Firebase, query with "a child exists" as a condition?
const oldItemsQuery = ref.orderByChild('creation')startAt("").endAt(cutoff);
Doing this I have no results in the query response.
Change this:
const oldItemsQuery = ref.orderByChild('creation').endAt(cutoff);
into this:
const oldItemsQuery = ref.orderByChild('creation').equalTo(cutoff);
equalTo
Creates a Query that includes children that match the specified value.
Using startAt(), endAt(), and equalTo() allows us to choose arbitrary starting and ending points for our queries.

best practice for search data at json object id using map

Let me how to find a json in javascript.
Sample Json:
{
"Employees" : [
{
"userId":"rirani",
"jobTitleName":"Developer",
"preferredFullName":"Romin Irani",
"employeeCode":"E1",
"region":"CA",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
},
{
"userId":"nirani",
"jobTitleName":"Developer",
"preferredFullName":"Neil Irani",
"employeeCode":"E2",
"region":"CA",
"phoneNumber":"408-1111111",
"emailAddress":"neilrirani#gmail.com"
}
]
]
}
the above json i want find particular userId based on employeeCode,emailAddress ad PhoneNumber. currently i am doing like below
for(var i=0; i<json.length;i++){
if((employeeCode==code)&&(emailAddress ==email)&&(PhoneNumber==phone)){
//here i am getting userId
}
}
I want know if this is the correct way. If it is small json load it ok. but if it's large scale of data what i have to do.
You can simply use the map function on the Employee array:
var data = {
"Employees" : [
{
"userId":"rirani",
"jobTitleName":"Developer",
"preferredFullName":"Romin Irani",
"employeeCode":"E1",
"region":"CA",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
},
{
"userId":"nirani",
"jobTitleName":"Developer",
"preferredFullName":"Neil Irani",
"employeeCode":"E2",
"region":"CA",
"phoneNumber":"408-1111111",
"emailAddress":"neilrirani#gmail.com"
}
]
};
var code ='E2' , email ='neilrirani#gmail.com' , phone = '408-1111111', userId;
data.Employees.map(x=>{
if(x.employeeCode == code && x.phoneNumber == phone && x.emailAddress== email){
userId = x.userId;
}
});
console.log(userId);
You can use find method which accepts a callback provided function applied on every item in the array.
The find() method returns the value of the first element in the array
that satisfies the provided testing function. Otherwise undefined is
returned.
let emailAddress="neilrirani#gmail.com";
let phone="408-1111111";
let code="E2";
let Employees = [
{
"userId":"rirani",
"jobTitleName":"Developer",
"preferredFullName":"Romin Irani",
"employeeCode":"E1",
"region":"CA",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
},
{
"userId":"nirani",
"jobTitleName":"Developer",
"preferredFullName":"Neil Irani",
"employeeCode":"E2",
"region":"CA",
"phoneNumber":"408-1111111",
"emailAddress":"neilrirani#gmail.com"
}
];
let employee=Employees.find(function(employee){
return employee.emailAddress==emailAddress && employee.phoneNumber==phone && employee.employeeCode==code;
});
console.log(employee.userId);

how to get all child data from firebase from two tables

I am trying to retrieve data from two tables in a database. But with child it is not working
I have this:
offers{
"id" : {
"quantity": "50%"
"store" : {
"id" : true
}
}
"store":{
"id":{
address:"location"
"users":{
"id": true
}
}
}
"users" : {
"name": "tom",
"lastname": "levine"
}
this is my structured data I want to get all child data from my table something like this:
{
"quantity":"50%",
"store":{
address:"location",
"users":{
"name": "tom",
"lastname": "levine"
}
}
}
}
I have this
const db = firebase.database();
db.ref('offers').child(id).once('value', (data) =>{
console.log(data.val())
}
but if I add another .child(store) then just return the stores id of that offer
I have the offer id, the store Id that I want and all the users if the have name tom for example.
how can I do that?
You should use a different structure for your database. NoSQL is more performant if you store data like you want to retrieve it.
But you can do what you want with something like that :
(It's just an example, you probably need to update and fix this code)
db.ref("offers").child(id).once("value", function(snapshot) {
var offerKey = snapshot.key;
var offerValue = snapshot.val();
snapshot.forEach(function(childSnapshot) {
var offerChildKey = childSnapshot.key;
var offerChildData = childSnapshot.val();
var quantity = offerChildData.quantity;
var store = offerChildData.store;
// Use quantity
Object.keys(store).forEach(function (storeKey) {
db.ref("store").child(storeKey).once("value", function(snapshot) {
var storeKey = snapshot.key;
var storeValue = snapshot.val();
var address = storeValue.address;
var users = storeValue.users;
// Use address
Object.keys(users).forEach(function (userKey) {
db.ref("users").child(userKey).once("value", function(snapshot) {
var userKey = snapshot.key;
var userValue = snapshot.val();
var name = userValue.name;
var lastname = userValue.lastname;
// Use name and lastname
}
});
}
});
});
}

Categories

Resources