This question has been asked before, but none of the solutions provided seem to help my problem:
I have an array of data on Firebase, that I loop through to generate content in my app, using a "for" loop and therefore an index value. This works fine with the predetermined sets of data, as the IDs are simple array numerics but when a user adds some new data, which is added to the array with push(), firebase creates a unique node key (such as -KyWRU7RRCE_V1w_OiZx) for the new set of data which for some reason prevents my loop from working (no errors shown in console).
If I go to firebase and manually ensure that the new set of data has a numeric value, loop starts working again. How do I make it so that when the user pushes new data to the array, the key being generated is numeric? I tried this:
// Push new routine to Firebase.
var firebaseRef = firebase.database().ref();
var createdExercise = JSON.parse(localStorage.newRoutine);
$("#save").click(function()
{
firebaseRef.child("workouts").key(some_indexed_value).push(createdExercise);
});
but the console returns the following error: Uncaught TypeError: firebaseRef.child(...).key is not a function.
In case it is useful, here is the loop I am using:
// Initialize Firebase.
firebase.initializeApp(config);
// Reference data.
var dbRef = firebase.database().ref().child("workouts");
// Sync with Firebase in real time.
dbRef.on("value", snap =>
{
var workouts = snap.val();
for (var i = 0; i < workouts.length; i++)
{
var routine = workouts[i].title;
var time = 3;
var exercises = workouts[i].exercises;
var icons;
$("#cardList").append(createCards(routine));
}
});
And a pic of my JSON data on Firebase:
Answer to your question is using .set() instead of .push() like this
firebaseRef.child("workouts").child(some_indexed_value).set(createdExercise);
this will create a node under workouts with your custom key.
but it is recommended to use push keys and use forEach() method to get the result than using for loop
Related
firebase snippit
Hello all. I am creating a web app that pulls from a firebase realtime database I have created. Using javascript I would like to pull the data from a specific node (i.e. "8").
I will then use the keys and values from the node in the web app.
What js/firebase code do I need to pull data from any specific node?
Below is the code we have tried. Long term goal is to pull data from a random node, but right now I just to find out how to pull from a specific node. Since the nodes are always going to be a number from 0-49, I don't need to use "length of array" functions when randomizing. I will use "Math.floor(Math.random() * 49" to give me a random number which I can pass into the index value for the node when I figure out how to access one specifically.
ref = firebase.database().ref('articles/');
function setupObservers() {
ref.on('value',function(snapshot){
console.log(snapshot.val())
let articleArray = []
for(key in snapshot.val()) {
let articleKeys = snapshot.val()[key]
articleArray.push(articleKeys)
}
randomArticle(articleArray)
})
}
function randomArticle(articleArray) {
let random = articleArray[Math.floor(Math.random() * articleArray.length)]
console.log(random)
}
setupObservers()
Thanks in advance!!
To read the value from a specific child node of which you know the key, you simply do:
ref = firebase.database().ref('articles');
ref.child("8").on('value',function(snapshot){
console.log(snapshot.val())
});
Hopefully a relatively simple question here with using Firestore querys
I am trying to create essentially a news feed, sorting the newest content from the oldest content. That part is pretty easy, I use:
var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);
Which retrieves the 3 newest entries in the news feed. My then idea is in the next query, to pull down the next 3 items in the feed. So if we are going by age, 4,5,6 in the collection in terms of how new the items are.
To do this I grab the last item in query one, and use that node's timestamp as my start at value in query 2:
var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);
first.get().then(function (documentSnapshots) {
// Get the last visible document
var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(lastVisible.data().timestamp).limit(3);
next.get().then(function(docSn){
console.log("SECOND QUERY!")
docSn.forEach(function(doc) {
console.log(doc.data().message)
})
})
The Result of this code returns the same as the first query returns, the nodes 1, 2, 3 despite trying to tell the second query to start at node3
I also tried passing in a javascript object instead:
var datevalue = Date.parse(lastVisible.data().timestamp)
var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(datevalue).limit(3);
Which also unfortunately did not work.
I also tried passing in the entire snapshot item, and got the error
"Malforormed Calls from JS: field sizes are different.
[[9,38,38,38],[0,0,1,0],
etc.."
Not really clue where to start with this as I have read through the docs and any examples and I could find and can't seem to figure it out. The only other way I can think of implementing this is by using a Cloud Function to number each node upon creation.. but that feels hacky
Any help would be huge! Thanks
I have a collection called "books" with a field called "created" of type Timestamp. This is not a string. This is not a Date. Please see the Timestamp docs. You need to specify in your settings that you want to use the new Timestamp type instead of Date for your timestamp fields. (See docs for firestore settings)
Example of initiating your firestore and set the TimestampsInSnapshots setting:
var firebaseApp = firebase.initializeApp({
apiKey: [APIKEY],
authDomain: [FIREBASEAPPDOMAIN],
projectId: [PROJECTID]
});
var firestore = firebase.firestore();
var settings = { timestampsInSnapshots: true }; // force Timestamp object instead of Date
firestore.settings(settings);
When this is done, i've run the below code and I get the expected results. First query returns three results. Newest first, latest last.
The second query returns the next three items.
var first = db.collection('books').orderBy("created", "desc").limit(3);
console.log("FIRST QUERY!")
first.get().then(function(documentSnapshots) {
documentSnapshots.forEach(function (doc) {
console.log(doc.data().created.toMillis())
});
// Get the last visible document
var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1];
var next = db.collection('books').orderBy("created", "desc")
.startAfter(lastVisible.data().created).limit(3);
next.get().then(function (docSn) {
console.log("SECOND QUERY!")
docSn.forEach(function (doc) {
console.log(doc.data().created.toMillis())
});
});
});
The console from the above code:
FIRST QUERY!
1540573716371
1540573676652
1540573668643
SECOND QUERY!
1540573658893
1540573536420
1540536647891
Are you checking the entire list returned? Or, just the first node?
If you use startAt, then the first node in the second list will be the last node in the first list (docs). I suggest using startAfter (docs).
Example:
var db = firebase.firestore()
var query = db.collection('feeds/0/active').orderBy('timestamp', 'desc').limit(3)
query.get().then((firstSnapshot) => {
var first3 = snapshot.docs
query.startAfter(first3[2]).get().then((nextSnapshot) => {
var next3 = snapshot.docs
})
})
I am trying to write a Firebase Cloud Function that takes all the users from my database and edits values within them. However, in order to do that I need a quick way for the code in my Cloud function to receive all of the user-ids from the database. For now, I have the function print the data it gets from the database so I know what I am working with.
The result is this:
{"WNGOuQqZhZSo5UFovgmgEAVX3Gz1":{"displayName":"jack","email":"test2#gmail.com"},"aRaZVJorkYNwCSzAbMkNJiGwzJm2":{"displayName":"testing","email":"testing#gmail.com"}}
I just need the two userIds instead.
This is the part of database I am working with:
This is the code:
If anyone knows what I need to change I would really appreciate it! Thanks!
I think you need to have a for - in loop over value. Below is the pseudocode -
var value = snapShot.val();
let namesArray = [];
for (var key in value) {
if (value.hasOwnProperty(key)) {
namesArray.push(key);
}
}
As with what jaibatrik said, you need to iterate over your objects.
You can't get the key without fetching the whole object.
In addition to running a for loop you can run a forEach over the snapshot.
const uids = [];
snapShot.forEach(single => {
uids.push(single.key);
});
The other option is to get all the keys from the snapShot.val() object.
const value = snapShot.val();
const uids = Object.keys(value);
Both ways are effectivly the same thing, just a preference on which way you prefer to do things
I am using algolia javascript api for retrieving all records in my index using browse function, but still it is returning 1000 records. Here is my code:
function load_location_list(){
var client = algoliasearch('ID', 'KEY');
var index_name = "locations_new";
var attribute_list = "*";
var index = client.initIndex(index_name);
index.browse({
"attributesToRetrieve": attribute_list,
}).then(function search_Success(response) {
console.log(response);
});
}
Actually, browse doesn't return more than 1000 elements at the first call. However, the response contains a cursor that you can use to access the next elements with the browseFrom function.
However, the previous method is kind of manual. You probably want to use the browseAll function instead which lets you access all the elements sequentially.
You can find more informations about all the browse* functions in the README of the JS client (also available in the Algolia documentation).
I'm using AngularJS and Firebase and trying to get the first child from a filtered set of children but limitToFirst(1) doesn't seem to get the first child like .child("=KDhddgd47nd") does
Like this
var Sport = new Firebase(FirebaseUrl);
var Teams = Sport.child("teams");
var myTeam = Teams.child("Saints");
var myPlayers = myTeam.child("players").orderByChild("name");
var myFixtures = myTeam.child("fixtures").startAt(now).orderByChild("date");
So I have a collection of fixtures now (myFixtures)
*var myFirstFixture = myFixtures.child("-KDUNN5KRNUmLlOhUB4D");*
works and gets the fixture where -KDUNN5KRNUmLlOhUB4D = the id of the fixture
but
var myFirstFixture = myFixtures.limitToFirst(1);
does not get the same result, ie. doesn't get a fixture at all
It should though shouldn't it?
Hmm... Im preety sure you have to attach a call-back as this doc refers to.. May you try doing this and updating us with results?
var myFirstFixture = myFixtures.limitToFirst(1).on("child_added", function(snapshot) {
console.log(snapshot.key() , snapshot.val());
});
An educated guess is that you're using:
$scope.fixture = $firebaseObject(myFirstFixture);
This will work when you have a direct Firebase reference to that first fixture, as when you do myFixtures.child("-KDUNN5KRNUmLlOhUB4D").
It will however not work when you use a query. Since there may be multiple items that match your conditions, a query will always return a list of items. Even when there is only one matching fixture, the query will still result in a list of one fixture. So you'll need to map it to an array:
$scope.fixtures = $firebaseArray(myFirstFixture);
And then ng-repeat over it in your view HTML.