Most efficient way to increment a value of everything in Firebase - angularjs

Say I have entries that look like this:
And I want to increment the priority field by 1 for every Item in the list of Estimates.
I can grab the estimates like this:
var estimates = firebase.child('Estimates');
After that how would I auto increment every Estimates priority by 1?

FOR FIRESTORE API ONLY, NOT FIREBASE
Thanks to the latest Firestore patch (March 13, 2019), you don't need to follow the other answers above.
Firestore's FieldValue class now hosts a increment method that atomically updates a numeric document field in the firestore database. You can use this FieldValue sentinel with either set (with mergeOptions true) or update methods of the DocumentReference object.
The usage is as follows (from the official docs, this is all there is):
DocumentReference washingtonRef = db.collection("cities").document("DC");
// Atomically increment the population of the city by 50.
washingtonRef.update("population", FieldValue.increment(50));
If you're wondering, it's available from version 18.2.0 of firestore. For your convenience, the Gradle dependency configuration is implementation 'com.google.firebase:firebase-firestore:18.2.0'
Note: Increment operations are useful for implementing counters, but
keep in mind that you can update a single document only once per
second. If you need to update your counter above this rate, see the
Distributed counters page.
EDIT 1: FieldValue.increment() is purely "server" side (happens in firestore), so you don't need to expose the current value to the client(s).
EDIT 2: While using the admin APIs, you can use admin.firestore.FieldValue.increment(1) for the same functionality. Thanks to #Jabir Ishaq for voluntarily letting me know about the undocumented feature. :)
EDIT 3:If the target field which you want to increment/decrement is not a number or does not exist, the increment method sets the value to the current value! This is helpful when you are creating a document for the first time.

This is one way to loop over all items and increase their priority:
var estimatesRef = firebase.child('Estimates');
estimatesRef.once('value', function(estimatesSnapshot) {
estimatesSnapshot.forEach(function(estimateSnapshot) {
estimateSnapshot.ref().update({
estimateSnapshot.val().priority + 1
});
});
});
It loops over all children of Estimates and increases the priority of each.
You can also combine the calls into a single update() call:
var estimatesRef = firebase.child('Estimates');
estimatesRef.once('value', function(estimatesSnapshot) {
var updates = {};
estimatesSnapshot.forEach(function(estimateSnapshot) {
updates[estimateSnapshot.key+'/priority'] = estimateSnapshot.val().priority + 1;
});
estimatesRef.update(updates);
});
The performance will be similar to the first solution (Firebase is very efficient when it comes to handling multiple requests). But in the second case it will be sent a single command to the server, so it will either fail or succeed completely.

Related

Flink: Can we update a keyed state for only some elements in processBroadcastElement function?

As mentioned in the answer here, I can use applyToKeyedState to update all states across all keys in the same manner.
If my broadcast event has a subset of all keys and I only want to update those, can I make it a part of the KeyedStateFunction?
Example
ctx.applyToKeyedState(stateDescriptor, new KeyedStateFunction[K, ValueState[Boolean]]() {
override def process(k: K, state: ValueState[Boolean]): Unit = {
val key = k.asInstanceOf[String]
if (broadcastEvent.contains(key)) {
state.update(true))
}
}
})
Nothing prevents you from employing whatever logic you desire in your KeyedStateFunction, but you could get yourself into trouble. The issue is this: each instance of your keyed broadcast function operator will be applying this function independently. And the job might crash at any point -- perhaps after some instances have applied the KeyedStateFunction, and others have not.
You should limit yourself to operations on the keyed state that will never give rise to inconsistencies, even after failure/recovery or after rescaling.

Custom query filter

I have entities in my datastore like this:
class Location(ndb.Model):
x = ndb.IntegerProperty(required = True)
y = ndb.IntegerProperty(required = True)
(other properties here)
Now I need to filter the entities in my datastore based on their distance from a user defined location. Can I somehow pass a function that checks if the location is correct as a filter, or is there a better approach to this?
Directly using the datastore, definitely not.
You would need to grab everything and do the computations via your code.
for instance if your userLocation is (5,4), and you have a max distance of 10, you would need to grab everything with x>-5 and x<15 and y>-6 and y< 14 and manually take off those who are too far.

Django: lock particular rows in table

I have the following django method:
def setCurrentSong(request, player):
try:
newCurrentSong = ActivePlaylistEntry.objects.get(
song__player_lib_song_id=request.POST['lib_id'],
song__player=player,
state=u'QE')
except ObjectDoesNotExist:
toReturn = HttpResponseNotFound()
toReturn[MISSING_RESOURCE_HEADER] = 'song'
return toReturn
try:
currentSong = ActivePlaylistEntry.objects.get(song__player=player, state=u'PL')
currentSong.state=u'FN'
currentSong.save()
except ObjectDoesNotExist:
pass
except MultipleObjectsReturned:
#This is bad. It means that
#this function isn't getting executed atomically like we hoped it would be
#I think we may actually need a mutex to protect this critial section :(
ActivePlaylistEntry.objects.filter(song__player=player, state=u'PL').update(state=u'FN')
newCurrentSong.state = u'PL'
newCurrentSong.save()
PlaylistEntryTimePlayed(playlist_entry=newCurrentSong).save()
return HttpResponse("Song changed")
Essentially, I want it to be so that for a given player, there is only one ActivePlaylistEntry that has a 'PL' (playing) state at any given time. However, I have actually experienced cases where, as a result of quickly calling this method twice in a row, I get two songs for the same player with a state of 'PL'. This is bad as I have other application logic that relies on the fact that a player only has one playing song at any given time (plus semantically it doesn't make sense to be playing two different songs at the same time on the same player). Is there a way for me to do this update atomically? Just running the method as a transaction with the on_commit_success decorator doesn't seem to work. Is there like a way to lock the table for all songs belonging to a particular player? I was thinking of adding a lock column to my model (boolean field) and either just spinning on it or pausing the thread for a few milliseconds and checking again but these feel super hackish and dirty. I was also thinking about creating a stored procedure but that's not really database independent.
Locking queries were added in 1.4.
with transaction.commit_manually():
ActivePlayListEntry.objects.select_for_update().filter(...)
aple = ActivePlayListEntry.objects.get(...)
aple.state = ...
transaction.commit()
But you should consider refactoring so that a separate table with a ForeignKey is used to indicate the "active" song.

WCF DataService 5 Any on single Entity (Client-Side)

I have a question according to the WCF Data Services 5.0.1 Any/All-Features. I want to use it in a Silverlight 5 Application and I want to query against an Entity called "Employee" (with a unique EmpNo=personalNr) and check if it already exists (therefore, I check if there is an Employee with the same personalNrfor validation purposes)..
In older versions it was not possible to do this on the Client. I had to call a custom Service Operation on the Server which returned a boolean value.
Is there a way to do this on the Client likes this (and get a boolean value as a result):
bool result = this.Context.Employees.Any(e => e.PersonalNr.Equals(personalNr, StringComparison.OrdinalIgnoreCase));
Thanks in advance!
Steve
The any/all feature is only usable inside the filter expression and it is used to query based on related entities or collection properties. If you want to check just for existence of an employee without any relationship, you can do that without any/all. The idea is to simply filter all employees on the given condition and see if you get at least 1 result back.
Now since you're doing this in Silverlight, the operation must be asynchronous, so a simple statement like above will not work. You could do something like:
var query = (DataServiceQuery<Employee>)this.Context.Employees.Where(e => e.PersonalNr.ToLower() == personalNr.ToLower()).Take(1);
query.BeginExecute((ar) =>
{
var results = query.EndExecute(ar);
// The usage of Any here is simply because it's the easiest way to do this
// and it is not used over OData/WCF DS, this is simply checking if the results returned
// from the service contain at least one result.
bool employeeExists = results.Any();
}, null);
Few notes about the code above:
The WCF Data Services doesn't support the Equals method with comparison options and the OData protocol doesn't support case insensitive string comparison either. So to workaround that, simply convert all values to lower case before comparing.
The Take(1) is used to only ask for the first value which matches the condition. Since we're only gonna use the existence of the result anyway, we don't need to ask the service for all the results (small optimization).

Why does it increase each time?

I want to understand why the number of timer keeps increasing whenever it is in use.
Should it start from a fresh number each time?
And why does it increase 2 or 4 each but not 1?
$(document).ready(function(){
endAndStartTimer();
});
var timer;
function endAndStartTimer() {
window.clearTimeout(timer);
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},1000);
alert(timer);
}
Do I need window.clearTimeout(timer); inside the function? What would it be wrong if I d
you can try it here.
Thanks.
Some simple facts
You don't have to call clearTimeout before setting one. At least not in the code you provided.
When I run your JSFiddle in FF4 it always reports 2
Timer IDs are generated by Javascript engine implemented in the browser so you don't have much control over it. Whatever it returns is value that you have to use to clear it. I haven't tested it but it may as well be that these ID generators are implement in a different way. Although the simplest (=fastest) way is by simply incrementing the ID of the last timer ID.
The method returns unique timer ID. The only purpose is to give you a handle to use it with clearTimeout. You can't control what id is generated.

Resources