I can't randomly get user from firebase
I'm doing dating app with react native and firebase.
Users can log in with google and set their accounts, but I can't match users.
I can pick 1 user but cant display user's data.
I tried:
i tried get all users from firebase realtime database
i can pick 1 user and log user's details but cant display in app
And sometimes user.uid returns null even if i logged in.
function getRandomUser() {
const numberOfUsers = 15;
const randomIndex = Math.floor(Math.random() * numberOfUsers);
var ref = firebase.database().ref("/users/");
ref
.limitToFirst(1)
.once("value")
.then((snapshot) => {
var randomUser = snapshot.val();
console.log(randomUser);
console.log(randomUser.bio);//this is not even display in console
});
}
I believe you should change the way you are referencing your database, so it should be var ref = firebase.database().ref("users"); and not var ref = firebase.database().ref("/users/");.
After that, are some changes related to the random number number and to the comparing issues that you need to perform, so values are returned. Please, give it a try using the below code.
var dbUser = firebase.database();
var refUser = dbUser.ref("<collection>");
refUser.orderByChild("online").equalTo(1).on("value", function(Data){
var numberOfUsers = 15;
var randomIndex = Math.random() * numberOfUsers;
var userIndex = parseInt(randomIndex, 10); //parse the random number from double to integer
var currentIndex = 0;
var BreakException = {};
try
{
Data.forEach(function(snap){
if(currentIndex==userIndex){
var randomUser = snap.val();
//Do something with your random user
throw BreakException;
}
currentIndex++;
});
}
catch(e){
if(e!== BreakException) throw e;
}
While this code is untested, it was based in this successful use case here and I believe should help you. Besides that, you can get another way of returning random users, but with indexes now, by checking this similar case here, with a very complete answer from a Product Lead from Firestore.
Related
I am new to the Apps script and trying to compare two email lists,
emails from google contacts
and emails from a google sheet (column B),
I want to delete email/s from Google Contacts that are not listed in the google sheet.
I got partial code from here and trying to modify it for my use, however, I stuck in the last part to detect the email that is not in the google sheet and then delete it from google contact.
Here is what I could put together, Extracting emails from Google contacts and Google sheet works fine.
running the following code does not work, but I don't get any error either.
Edited: I am not sure the first part of the code that extracts data from google contacts is in one array, because each email is printed like this when used console.log: [email1#email.com]
Appreciate your help to make it work.
function deleteContacts() {
var contactEmails = ContactsApp.getContacts().map(function(contact) {
return contact.getEmailAddresses();
//console.log("Google Emails:" + contactEmails);
var sheet = SpreadsheetApp.getActive().getSheetByName("sheet2");
var ColEmails = sheet.getRange('B2:B').getValues().map(function(value) {
return value[0];
}).filter(function(val) {
return val != "";
})
//console.log("Sheet Emails:" + ColEmails);
for (var i = 0; i < contactEmails.length; i++) {
if (ColEmails.indexOf(contactEmails[i]) == -1) {
var contact = ContactsApp.getContactsByEmailAddress(contactEmails[i]);
ContactsApp.deleteContact(contact);
}
}
});
}
Try:
function deleteContacts() {
const ss=SpreadsheetApp.getActive();
const sh = ss.getSheetByName("sheet2");
const rg = sh.getRange(2,2,sh.getLastRow()-1,1);
const vs = rg.getValues().flat();
const emails = ContactsApp.getContacts().map(function (contact) {return contact.getEmailAddresses();}).flat();
emails.forEach(e=>{
if(!~vs.indexOf(e)) {
ContactsApp.getContact(e).deleteContact()
}
});
}
can anybody help me? I'm having a problem similar to the previous post. I'm just not getting the child object. I have tried in several ways the most basic and logical would be: newPost.musician.statusbatera
Follows a chrome debug print: --Screen Shot--
I'm not getting it because of the key generated automatically by firebase as the print in attached.
My code:
var db = firebase.database();
var ref = db.ref("users");
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
console.log("Musician: " + newPost.musician.statusbatera);
});
You can grab the autogenerated key using Object.keys, then you can assign the object you need:
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
keys = Object.keys(newPost.musician)
console.log("Musician: " + newPost.musician[keys[0]].statusbatera);
});
in theory, there should be only one value in keys...
I think you want to iterate through musician's list, if so, give this a try :-
for(var i = 0; i <= newPost.musician.lenght; i++) {
console.log("Musician: " + newPost.musician[i].statusbatera);
}
I have this database
service/
-KSxobYDhjUJeSvu3dC1
-Accion:"Nueva ronda"
-Codigo: 3
-dateTime: 1475284727
-notify: 0
-num_mesa: 0
-KSxobptdYSc-qrCSbyU
-Accion: "Orden cancelada"
-dateTime: 1475284728
-notify: 0
-num_mesa: 0
and then I have this code:
ref.orderByChild("notify").equalTo(1).limitToLast(1).on("child_added", function(snapshot) {
var changedPost = snapshot.val();
var mykey = snapshot.key;
if(changedPost.notify == 1 ){
var message = "New action "
console.log(serviceArray[mykey].notify);//undefined
$scope.showActionToast(message);
}
});
This code will read the last entry in the database and show a toast, notifying that a new action has been inserted in firebase. It shows the toast.
My problem is that I don't want it to show every time i reload the page.
So I thought about adding a simple flag that if it was shown in a toast, it will change notify to 0.
My problem is that I have service that returns a firebaseArray named serviceArray. When I try to access the row to change the value it says undefined. How can I change the value in the same function?
You're going to be better off simply tracking the timestamp of the last message you've shown to the user. With that you can query for messages that were added after that timestamp:
var timestampOfMostRecentlySeenMessage = null;
if (timestampOfMostRecentlySeenMessage) {
ref.orderByChild("timestamp")
.startAt(timestampOfMostRecentlySeenMessage)
.limitToLast(1)
.on("child_added", function(snapshot) {
var message = snapshot.val();
timestampOfMostRecentlySeenMessage = message.dateTime;
})
Now you just need to maintain the value of timestampOfMostRecentlySeenMessage between page reloads. You could do this in a cookie, in local storage of your browser or even in a user-specific part of your database:
var userRef = firebase.database().ref("users").child(user.uid);
userRef.child("timestampOfMostRecentlySeenMessage").set(timestampOfMostRecentlySeenMessage);
i just added a flag that declares after running the search for the first time.
ref.orderByChild("notify").equalTo(1).limitToLast(1).on("child_added", function(snapshot) {
var changedPost = snapshot.val();
var mykey = snapshot.key;
if(changedPost.notify == 1 && $scope.flag== 1 ){
var message = "New action "
console.log(serviceArray[mykey].notify);//undefined
$scope.showActionToast(message);
}
$scope.flag= 1;
});
I'm newbie with Firebase + GeoFire and I'm having trouble with geoFire query function.
I want to add in an array the results from geoQuery function and return it in a function. But the data I have manipulating inside geoQuery.on method seems out of scope or not available or due to promises, I dont know... the fact is outside the geoquery.on method the variable sellers is empty.
How can I return results from geoQuery and save it into a return variable
//Set seller position in firebase db
var setPosition = function() {
navigator.geolocation.getCurrentPosition(setPositionSuccess, error, options);
//navigator.geolocation.watchPosition(setPositionSuccess, positionError, { enableHighAccuracy:true })
};
//Get sellers near buyer position
var getSellersForCurrentPosition = function() {
navigator.geolocation.getCurrentPosition(getPositionSuccess, error, options);
//navigator.geolocation.watchPosition(positionSuccess, positionError, { enableHighAccuracy:true })
};
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var sellers = [];
var oneSeller = {};
var onKeyEnteredRegistration = geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
sellers.push(oneSeller);
});
var onReadyRegistration = geoQuery.on("ready", function() {
geoQuery.cancel();
});
return sellers;
}
By the way, how accurate is html5 geolocation? Is it different between desktop browser and mobile browser?
Geofire monitors the sellers in the range you indicate. Any time a seller enters/exits the range, it fires a key_entered or key_exited event. These events can happen at any time after you start the query. In JavaScript terms this is often described as: the callbacks happen asynchronously.
A simple event flow, might explain what happens best:
you call getPositionSuccess()
you start a Geoquery to monitor the sellers that are in range: geoFire.query()
no sellers are immediately in range, so your callback doesn't fire
the getPositionSuccess() function is done and exits
a seller comes in range
GeoFire fires the key_entered event and your callback runs
but getPositionSuccess() has already exited, so how can it return a value?
Even if you were to wait for the first seller to come into range before returning (not possible in a browser, but it is possible in other languages/environments), how will you return the value when a second seller comes in range?
For this reason, you have to deal with asynchronous data differently. Typically you do this by moving the code that would call the getPositionSuccess() function into the function.
Say you are now trying to do this:
var sellers = getPositionSuccess(pos);
sellers.forEach(function(seller) {
addSellerToMap(seller);
});
To handle the asynchronous nature of the events, you'd move this code into getPositionSuccess:
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var oneSeller = {};
geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
addSellerToMap(oneSeller);
});
}
I understand that in your use-case your sellers won't move, so it may be more intuitive to think of them as a static list. But even in this case, the results are loaded from a remote database and it will take some time before that data is loaded. The modern web loads data asynchronously and all your code will have to deal with it in a way similar to what I outlined above.
I'm using angularfire 1.1.1 to store my apps objects and each object creates associated indexes. So when a user is created, that user is added to the 'users' table and then the users index table gets keyed with the UID and points to the actual user's id.
When the main state is called, I run a checkAuth() method to see if a user is signed in. If so, then I want to assign $rootScope.auth = {id:userID, role: role} etc.
The function works great in my login method but i don't know how to grab the value from my checkAuth() method. I've tried $value on both $firebaseObject and $firebaseArray, also tried to call them with [0] since there is only one id value in the table for each user's uid.
The sloppy regex is for changing the semi-colon from SimpleLogin:47 to SimpleLogin-47 for keying to the index.
Here's the code that doesn't work:
function authCheck(){
var getAuth = $firebaseAuth(Data.ref);
console.log('signed in as', getAuth.$getAuth().uid);
var uid = getAuth.$getAuth().uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
var userIndexRef = Data.ref.child('index/users/uid/'+uid);
var userIndexArray = $firebaseArray(userIndexRef);
var userIndexObject = $firebaseObject(userIndexRef);
console.log(userIndexArray, userIndexObject);
var realId = '';
angular.forEach(userIndexObject, function(key, id){
realId = id;
$rootScope.auth = realId;
return realId;
});
}
Here's the login code that does work:
function login(email, pass) {
ref.authWithPassword({email:email,password:pass}, function(error, authData){
if (error) {
console.log(error);
} else {
console.log('signed in as',authData.uid);
var uid = authData.uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
angular.forEach(Data.dataObject.index.users.uid[uid],function(id, key){
$rootScope.role = Data.dataObject.users[id].role;
$rootScope.auth = {authData:authData, id:id, role:Data.dataObject.users[id].role};
});
}
});
}
If anyone sees where I've messed up, I'll be happy to know. Here's the repo https://github.com/irthos/medviz if it helps. Thank you very much!