It seems I can retrieve all my data from my Firebase Realtime Database with the following:
let itemsRef = firebaseApp.database().ref('/');
itemsRef.on('value', (snapshot) => {
let data = snapshot.val();
let item = Object.values(data);
this.setState({item});
});
But when I try to query with specific parameters instead of just retrieving all the information, I always end up with this error:
#firebase/database: FIREBASE WARNING: Exception was thrown by user callback.
TypeError: Cannot convert undefined or null to object
This is how I'm trying to query information... literally following the documentation, and somehow my code works when I retrieve all information but not when the only change I make is adding a query?
let itemsRef = firebaseApp.database().ref('/');
itemsRef.orderByChild('roundedBPM').equalTo('100').on('value', (snapshot) => {
let data = snapshot.val();
let item = Object.values(data);
this.setState({item});
});
Is anyone else having problems querying from Firebase or am I doing something wrong?
This is how my data is structured on Firebase:
I would try initializing firebase in dbConfig.js for instance like so:
import * as firebase from 'firebase';
let config = {
apiKey: "XXXXXXX",
authDomain: "XXXXX",
databaseURL: "XXXXX",
projectId: "XXXXX",
storageBucket: "XXXX",
messagingSenderId: "XXXX"
};
firebase.initializeApp(config);
export default firebase;
I would import firebase where it's:
import firebase from './dbConfig.js'
let itemsRef = firebase.database().ref('/');
itemsRef.orderByChild('roundedBPM').equalTo('100').on('value', (snapshot) => {
let data = snapshot.val();
let item = Object.values(data);
this.setState({item});
});
Note: OrderByChild the element roundedBPM needs to be a direct child to the root path '/' if it's a nested child you could do something like this:
let itemsRef = firebase.database().ref('/users');
itemsRef.orderByChild('roundedBPM').equalTo('100').on('value', (snapshot) => {
...
});
Note: if you are setting equalTo() roundedBPM when it's a number and not a string you wouldn't get back any data. Make sure you use the correct type of data.
I hope this will help!
Related
i have this issue of 'firebase is not defined' when i try to read and display data from the relatime database.
I am using firebase to host a simple site in which you input 4 values and receive a score back, everything is scored in the database. i then want to display the highest 10 scores from the database, and im having trouble doing that.
Ive seen lot of people having this issue, but their resolutions are not working for me
Here is my code
function displayTopScores() {
// Reference to the scores in the database
var scoresRef = firebase.database().ref("scores");
// Retrieve the top 10 scores
scoresRef.orderByChild("Score").limitToFirst(10).on("value", function(snapshot) {
var scores = snapshot.val();
// Array to store the top 10 scores
var topScores = [];
// Add the scores to the array
for (var score in scores) {
topScores.push(scores[score]);
}
// Sort the scores in descending order
topScores.sort(function(a, b) {
return b.Score - a.Score;
});
// Create a table to display the scores
var table = document.createElement("table");
table.setAttribute("class", "table table-striped");
// Add a header row to the table
var headerRow = table.insertRow(-1);
var nameHeaderCell = headerRow.insertCell(-1);
nameHeaderCell.innerHTML = "Name";
var scoreHeaderCell = headerRow.insertCell(-1);
scoreHeaderCell.innerHTML = "Score";
// Add a row for each score
for (var i = 0; i < topScores.length; i++) {
var row = table.insertRow(-1);
var nameCell = row.insertCell(-1);
nameCell.innerHTML = topScores[i].Name;
var scoreCell = row.insertCell(-1);
scoreCell.innerHTML = topScores[i].Score;
}
// Add the table to the HTML page
var scoresContainer = document.querySelector("#scores-container");
scoresContainer.innerHTML = "";
scoresContainer.appendChild(table);
});
}
const dbRef = ref(getDatabase());
get(child(dbRef, `scores/Scores`)).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
} else {
console.log("No data available");
}
}).catch((error) => {
console.error(error);
});
i have imported (i think) all the right things for this to happen, but i am clearly doing some mistake i have not figured out.
here is what i import:
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.15.0/firebase-app.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "---",
authDomain: "---",
databaseURL: "---",
projectId: "---",
storageBucket: "---",
messagingSenderId: "---",
appId: "---",
measurementId: "---"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
import {getDatabase, set, get, update, remove, ref, child}
from "https://www.gstatic.com/firebasejs/9.15.0/firebase-database.js";
const database = getDatabase();
I've read the documentation on how to import the database and app function, looked at other people with the same issue, tried to ask openAI but with no luck.
tried using different ways of creating a reference and read the data.
You need to pass the app variable as a parameter to getDatabase() it should be getDatabase(app)
Here is the official code from the firebase documentation:
import { initializeApp } from "firebase/app";
import { getDatabase } from "firebase/database";
const firebaseConfig = {
// ...
databaseURL: "https://DATABASE_NAME.firebaseio.com",
};
const app = initializeApp(firebaseConfig);
const database = getDatabase(app);
You can follow further examples from the documentation here: https://firebase.google.com/docs/database/web/start#web-version-9
function displayTopScores() {
const dbRef = ref(getDatabase());
get(child(dbRef, `scores/`)).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
document.getElementById("scores-list").innerHTML = console.log(snapshot.val());
} else {
console.log("No data available");
}
}).catch((error) => {
console.error(error);
});
}
its not complete solution cause i still cant show in my site the values from the database, but this seems to fix the issue at least in part, now i see the database getting read from the chrome dev tool
I have been trying to make an e-commerce website and in that almost all things are done except for the database part. In which I have to fetch the data from firebase and use it in the products section.
I have fetched the data in local variables, however I want to store the data in a global scoped object, but it is not working.
So what I basically want is I want to fetch the data from firebase(DONE) and store it in global scope object(PENDING) so that I can use this object in other .js files.
Any kind of idea/advice/help/suggestion in more than welcomed!!
Thanks in advance!
This is my code:
https://jsfiddle.net/kumartanwar123/gseh4coq/
OR
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-analytics.js";
// GLOBAL VARIABLES
var name, images, prices;
const firebaseConfig = {
apiKey: "--",
authDomain: "--",
databaseURL: "--",
projectId: "round-device-336118",
storageBucket: "round-device-336118.appspot.com",
messagingSenderId: "--",
appId: "--",
measurementId: "--",
};
const app = initializeApp(firebaseConfig);
firebase.initializeApp(firebaseConfig);
class firebase_class {
constructor(Images, Prices, Name) {
this.Images = Images;
this.Prices = Prices;
this.Name = Name;
}
}
// FIREBASE DATA FETCH
firebase
.database()
.ref("Practice")
.on("value", function (all_data) {
all_data.forEach(function (current_data) {
name = Object.keys(current_data.val().Name).map(
(keys) => current_data.val().Name[keys]
);
//In this if I use console.log(name) then it is working just fine, but not in outside the function.
images = Object.keys(current_data.val().Images).map(
(keys) => current_data.val().Images[keys]
);
prices = Object.keys(current_data.val().Prices).map(
(keys) => current_data.val().Prices[keys]
);
});
});
let firebase_object = new firebase_class(images, prices, name);
The problem is not where you access the database, but when you access it.
Data is loaded from Firebase (and pretty much all modern cloud APIs) asynchronously, and your main code (and thus the let firebase_object = new firebase_class(images, prices, name)) continues to execute while the data is loaded. Then when the data is available, your callback is invoked with it and it sets images, prices, and name.
And code that needs the data from Firebase has to be inside the callback, or be called from there. So:
// FIREBASE DATA FETCH
firebase
.database()
.ref("Practice")
.on("value", function (all_data) {
all_data.forEach(function (current_data) {
name = Object.keys(current_data.val().Name).map(
(keys) => current_data.val().Name[keys]
);
//In this if I use console.log(name) then it is working just fine, but not in outside the function.
images = Object.keys(current_data.val().Images).map(
(keys) => current_data.val().Images[keys]
);
prices = Object.keys(current_data.val().Prices).map(
(keys) => current_data.val().Prices[keys]
);
});
// 👇
let firebase_object = new firebase_class(images, prices, name);
... any use of firebase_object should be here too
});
Also check out:
Why Does Firebase Lose Reference outside the once() Function?
I'm starting a small project with Vuejs and Firebase. I am trying to upload Name and Price to Firestore. I checked their documentation and few tutorials, but I am stuck with this error.
<div class="form-group">
<v-btn v-on:click="saveData" class="btn btn-primary">Save data</v-btn>
</div>
import db from "../firebase";
export default {
name: "products",
props: {
msg: String,
},
data() {
return {
aon: {
Name: null,
Price: null,
},
};
},
methods: {
saveData() {
db.collection("Products")
.add(this.Product)
.then((docRef) => {
console.log("Document written with ID: ", docRef.id);
})
.catch((error) => {
console.error("Error adding document: ", error);
});
},
},
};
Here is my firebase.js
import firebase from '#firebase/app';
import '#firebase/auth';
import '#firebase/firestore';
const fb = firebase.initializeApp({
apiKey: "!!!!!!!!!!!",
authDomain: "!!!!!!!!",
databaseURL: "!!!!!!!",
projectId: "!!!!!!",
storageBucket: "!!!!!!!",
messagingSenderId: "!!!!!!!",
appId: "!!!!!!!!!",
measurementId: "!!!!!!!!!!!!"
});
const db = firebase.firestore();
export default firebase;
export {db,fb} ;
First you didn't initialized your firebase app. To do so :
//firebase.js
const db = firebase.initializeApp(fb)
export {db.firestore(),fb}
Then on your products page or component you wrote :
//products.vue
db.collection("Products").add(this.Product)...
this.Product object doesn't exist so it should be this.aon
//products.vue
db.collection("Products").add(this.aon)...
For more info : https://firebase.google.com/docs/firestore/quickstart
As per the documentation here and here you need to use the .set(), .add(), .update() and .doc() methods like this.
When you use set() to create a document, you must specify an ID for the document to create. For example:
await db.collection('cities').doc('new-city-id').set(data);
to let Cloud Firestore auto-generate an ID for you. You can do this by calling add()
// Add a new document with a generated id.
const res = await db.collection('cities').add({
name: 'Tokyo',
country: 'Japan'
});
console.log('Added document with ID: ', res.id);
In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later. For this use case, you can call doc()
const newCityRef = db.collection('cities').doc();
// Later...
const res = await newCityRef.set({
// ...
});
To update some fields of a document without overwriting the entire document, use the update() method:
const cityRef = db.collection('cities').doc('DC');
// Set the 'capital' field of the city
const res = await cityRef.update({capital: true});
I am trying to redefine all my apps database references so that I can write a specific set of of firebase rules (I need to add buildings and depts nodes inside the user node – read why: What is the best practice to write the rules of Firebase in a situation like this? ).
I am using a firebase-config.js and exporting all my app's database references to the app's components so hopefully if I change this path I don't have to refactor the code on all the app's components.
I am trying to do it with a function (on my firebase-config.js file):
import * as firebase from "firebase";
import { mapState } from 'vuex';
import { store } from './store/store';
var config = {
apiKey: "XXXXXXXX",
authDomain: "XXXXXXXX.firebaseapp.com",
databaseURL: "https://XXXXXXXX.firebaseio.com",
projectId: "XXXXXXXX",
storageBucket: "XXXXXXXX.appspot.com",
messagingSenderId: "XXXXXXXX"
};
firebase.initializeApp(config)
export default !firebase.apps.length ? firebase.initializeApp(config) : firebase;
firebase.auth().onAuthStateChanged((user) => {
if (user) {
let userRef = firebase.database().ref('users').child(user.uid);
let buildingsRef = userRef.child('buildings');
}
})();
export const db = firebase.database();
export const usersRef = db.ref('users');
_// BUT THIS: "buildingsRef" is returning undefined!!! :(
export const buildingsRef = db.ref('users'+ "/" + buildingsRef) //buildingsRef is a variable
export const deptsRef = db.ref('depts');
The buldingsRef variable is returning undefined and it's writing the buildings to an undefined node.
{
"users" : {
"6hwNde08Wuaa9bfReR28niSbOsF3" : {
"name" : "João Alves Marrucho",
"userEmail" : "joaoalvesmarrucho#hotmail.com"
},
"undefined" : {
"-L9M4lM7oZFfmJKorxjC" : {
"address" : "",
"name" : "b1",
"ownerID" : "6hwNde08Wuaa9bfReR28niSbOsF3"
}
}
}
}
I writing to the node with the following method (vue.js):
addBuilding: function () {
let userId = firebase.auth().currentUser.uid;
let buildingKey = buildingsRef.push().key
this.newBuilding.ownerID = userId;
buildingsRef.child(buildingKey).set(this.newBuilding);
}
Any thoughts on why the variable buildingsRef is returning undefined?
Here is my full firebase-config.js file: http://jsfiddle.net/UnXrw/85/
If I understand your question, I think you want something like this:
firebase.auth().onAuthStateChanged(user => {
if (user) {
let userRef = firebase.database().ref('users').child(user.uid);
let buildingsRef = userRef.child('buildings');
// now do whatever you want with those refs
}
});
I am trying to get a large dataset in Firebase database to Algolia for search indexing and every time I get a timeout error, what does that mean and how can I solve it?
I have created a node.js application to copy the data over and is as below. I can copy small data, say 10 contacts just fine, the problem is 3,000 contacts.
const algoliasearch = require('algoliasearch');
const dotenv = require('dotenv');
const firebase = require('firebase');
// load values from the .env file in this directory into process.env
dotenv.load();
// configure firebase
firebase.initializeApp({
databaseURL: process.env.FIREBASE_DATABASE_URL,
});
const database = firebase.database();
// configure algolia
const algolia = algoliasearch(
process.env.ALGOLIA_APP_ID,
process.env.ALGOLIA_API_KEY
);
const index = algolia.initIndex(process.env.ALGOLIA_INDEX_NAME);
// Get all contacts from Firebase
database.ref('/contactDetail/brazil').once('value', contacts => {
// Build an array of all records to push to Algolia
const records = [];
contacts.forEach(contact => {
// get the key and data from the snapshot
const childKey = contact.key;
const childData = contact.val();
// We set the Algolia objectID as the Firebase .key
childData.objectID = childKey;
// Add object for indexing
records.push(childData);
});
// Add or update new objects
index
.saveObjects(records)
.then(() => {
console.log('Contacts imported into Algolia');
})
.catch(error => {
console.error('Error when importing contact into Algolia', error);
process.exit(1);
});
});
I get a snippet of the contacts json and the following message:
contentLength: 854068,
method: 'POST',
timeouts: [Object],
url: '/1/indexes/app_NAME/batch',
startTime: 2018-01-17T20:35:27.239Z,
endTime: 2018-01-17T20:35:39.242Z,
duration: 12003 } ] }