Ok so I am making a like/dislike system for my website and I got it to work. The only problem is, is that a user can like something more than once, how do I stop this? heres my function
function thumbup(uid, s) {
const prevthumbs = s.thumbs
firebase.db.collection('users').doc(uid).update({
thumbs: prevthumbs + 1
})
}
How can I limit the increment to only one?
To limit how often the user can do something, use their UID as the key for the operation.
For example, if you don't have too many users, you can have a field likedBy in the document which is an array of the UIDs of the users who liked this user.
It's a bit unclear how to exactly implement it in your code for me, as you're already writing to a doc(uid), where usually the user is liking a post or something like that.
Related
This is an old question but no answers found. Old answers' source links are dead, old functions are deprecated.
I've look at these topics (1, 2) amongst others, and also current Firebase guide.
function writeUserData(name, win, loss) {
firebase.database().ref('users/').push({
name: name,
wins: win,
losses: loss
});
}
I need to pull or somehow convert the unique ID from each push to numeric ID: 1, 2
UPDATE:
Here's what I'm trying to do:
2 users can login at the same time from 2 different browsers.
1st user hits button 'log-in' or 'start' will be written as users/1/{user's attributes} on firebase.
if there's an existing user
(somehow I need to check that on the user-end), the next user hits
'start' will be written as users/2/{user's attributes} on firebase. Else (no existing user), the user will be written as user1. This is where I think I need push instead of set. I can use set to add more users from 1 browser, but if i open the app from another browser/chrome incognito, the app will just reset the existing users.
if a user refreshes or closes the browser, that user will be removed from firebase so another user can log-in.
I've tried different methods (loop, creating new var...) to achieve this.
Rather than .push, try to use .set or .update. In that way you can set your own generated key. But as already suggested, this may not be the best approach.
I have an application where users can follow other users. I want to have a real-time update system, display the total count of followers a user has.
I've just started playing around with Firebase and Pusher, but I don't understand one thing - will each user have their own 'channel'? How would I handle such thing as a follower counter update?
I followed the tutorial and saw that push method can create lists, so one solution I can see is having a list of all the users, each user being an object something like this:
{ username: 'john_doe', follower_count: 6 }
But I don't understand how would I actually track it on the front end? Should I have a filter, something like this?
var user = users.filter(function(user) { return user.username === 'john_doe'; });
// code to display user.follower_count
Or is there a different way that I'm missing?
Most of Firebase logic is based on listeners, you can add a listener to events happening in your collections and when those events happen, you do something.
One way to go about this would be:
var myFollowerListRef = new Firebase(PATH_TO_YOUR_COLLECTION);
myFollowerListRef.on("value", function(snapshot) {
console.log(snapshot.length);
});
This way, every time your follower collection changes, the asynchronous function fires and you can do what you want with the fresh data.
For more information:
https://www.firebase.com/docs/web/guide/retrieving-data.html
Hope this helps, I'm still a beginner in Firebase.
#Th0rndike's approach is the simplest and works fine for relatively short lists. For longer lists, consider using a transaction. From the Firebase documentation on saving transactional data:
var upvotesRef = new Firebase('https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction(function (current_value) {
return (current_value || 0) + 1;
});
But I recommend that you read the entire Firebase guide. It contains solutions for a lot of common use-cases.
I have a JSON data of news like this:
{
"news": [
{"title": "some title #1","text": "text","date": "27.12.15 23:45"},
{"title": "some title #2","text": "text","date": "26.12.15 22:35"},
...
]
}
I need to get a certain number of this list, depended on an argument in a function. As I understand, its called pagination.
I can get the ajax response and slice it immediately. So that every time the function is called - every time it makes an ajax request.
Like this:
function showNews(page) {
var newsPerPage = 5,
firstArticle = newsPerPage*(page-1);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
var newsArr = JSON.parse(xhr.responseText),
;
newsArr.news = newsArr.news.slice(firstArticle, newsPerPage*(page));
addNews(newsArr);
}
};
xhr.open("GET", url, true);
xhr.send();
Or I can store all the result in newsArr and slice it in that additional function addNews, sorted by pages.
function addNews(newsArr, newsPerPage) {
var pages = Math.ceil(amount/newsPerPages), // counts number of pages
pagesData = {};
for(var i=0; i<=pages; i++) {
var min = i*newsPerPages, //min index of current page in loop
max = (i+1)*newsPerPages; // max index of current page in loop
newsArr.news.forEach(createPageData);
}
function createPageData(item, j) {
if(j+1 <= max && j >= min) {
if(!pagesData["page"+(i+1)]) {
pagesData["page"+(i+1)] = {news: []};
}
pagesData["page"+(i+1)].news.push(item);
}
}
So, simple question is which variant is more effective? The first one loads a server and the second loads users' memory. What would you choose in my situation? :)
Thanks for the answers. I understood what I wanted. But there is so much good answers that I can't choose the best
It is actually a primarily opinion-based question.
For me, pagination approach looks better because it will not produce "lag" before displaying the news. From user's POV the page will load faster.
As for me, I would do pagination + preload of the next page. I.e., always store the contents of the next page, so that you can show it without a delay. When a user moves to the last page - load another one.
Loading all the news is definitely a bad idea. If you have 1000 news records, then every user will have to load all of them...even if he isn't going to read a single one.
In my opinion, less requests == better rule doesn't apply here. It is not guaranteed that a user will read all the news. If StackOverflow loaded all the questions it has every time you open the main page, then both StackOverflow and users would have huge problems.
If the max number of records that your service returns is around 1000, then I don't think it is going to create a huge payload or memory issues (by looking at the nature of your data), so I think option-2 is better because
number of service calls will be less
since user will not see any lag while paginating, his experience of using the site will be better.
As a rule of thumb:
less requests == better
but that's not always possible. You may run out of memory/network if the data you store is huge, i.e. you may need pagination on the server side. Actually server side pagination should be the default approach and then you think about improvements (e.g. local caching) if you really need them.
So what you should do is try all scenarios and see how well they behave in your concrete situation.
I prefer fetch all data but showing on some certain condition like click on next button data is already there just do hide and show on condition using jquery.
Every time call ajax is bad idea.
but you also need to call ajax for new data if data is changed after some periodic time
Not sure if I'm going about this the right way. I'll map out what I'm trying to achieve and please give me any feedback you can. Also very new to meteor so sorry if I'm a bit uneducated in some aspects. This is going to be a two player game where users login in with accounts-twitter or accounts-facebook. Here's the tricky part it will only initialize the game if there are two users logged in. To figure out who is logged in I have put this line of code in my server portion:
if (Meteor.isServer) {
Meteor.publish("userStatus", function() {
return Meteor.users.find({
"status.online": true
})
});
}
My idea of what needs to be done is write an if statement if(userStatus === true){get a users "_id"} then push that user into an array and have a for loop run through every 2 users signed on in the array and initialize a game for them. Also the main question is how do I grab the users ID if status.online is true? Also any input on how to make this more efficient is much appreciated.
Answering your "main question," you would do this with a mongoDB for-each like so.
Meteor.methods({
getOnline : function(){
var retArr = new Array();
Meteor.users.find({"status.online": true}).forEach(function(u){
retArr.push(u._id); //populated retArr with the id of users online
});
return retArr;
}
});
If I left out something or you need clarification on something, please comment.
I will put this post into paragraphs to make it easier reffering to specific content.
I have made a simple button in html that plusses a number with 1 everytime the button is pressed. This function is made in Javascript. This number has to be put into the database every 20 seconds.
Since Javascript is running on the client side, every visiter will be able to change the current number of times the button is pressed, and that "fake" number will then be sent to the database after 20 seconds.
The user should not be able to change this number, because it's considered cheating.
I could use other languages to complete this like java, flash etc. but I need to make it working with Javascript/Jquery that runs on the client side. The reason for this is that it will take too hard on the server if there is sent a request to the server everytime to button is pressed.
I hope you understand all 4 steps, if not please let me know which step I shall deepen.
Question: How can I make a secure way of processing a number from the client-side to the database without the user being able to change that number on their computer? If I can't, any other suggestions?
Thanks in advance.
First of all, your counter should be on your server. Don't let the client side tell you how many times the button has been pressed - store this yourself on the server (where no one can reach).
This will mean that you'll have to notify the server every time the user clicks the button. Furthermore, you'll need to make sure that each "click" is valid. You could do this by attaching a unique key to each of the buttons clicks. As soon as the user clicks the button, this key will be sent to the sever and validated. If it is valid, the server will return a new key to be sent when the button is next clicked.
You should be aware that it is very VERY easy to write a short jQuery script to manipulate clicks on DOM elements though. A command as simple as
setInterval(function(){
$('button').trigger('click');
},500);
Would trigger a click event on the button every 500 milliseconds (0.5 seconds).
Code that runs in JavaScript can't practically be protected against "cheating". Your best bet might be data hiding:
var myobj = (function() {
var i = 0;
return {
function setI(newvalue) {
// do checks here
if (true) {
i = newvalue;
}
},
function sendI() {
// send value of i
}
}
}());
myobj.setI(123);
myobj.sendI();
myobj.i // undefined
Moving the logic that prevents data tampering to the server is better though.