0

I have the following structure. Each user has his own data.

---+ root_child
   |
   +---+ Gy7FXRbRjDfAKWu7a95NgiGIZUk1  (Firebase User Id)
       |
       |
       +---+ KlNlb71qtQUXIGA4cNa (random key, generated by Firebase)
       |   |
       |   +--- timestamp = 1234567890
       |   |
       |   +--- (other data field ...)
       |
       |
       +---+ KlNlcmfMTDjxQ0BwW1K
       |   |
       |   +--- timestamp = 9876543211
       |   |
       |   +--- (other data field ...)
       |
       |
       +---+ (...)

Adding records occurs in this way:

databaseReference = FirebaseDatabase.getInstance().getReference("root_child");
databaseReference.child(firebaseUser.getUid())
    .push()
    .setValue(val);

push() ... Locations generated on a single client will be sorted in the order that they are created...

Now, how can I leave only 100 newest entries (for the specified user id) and delete all the rest?

Pseudocode :

databaseReference = FirebaseDatabase.getInstance()
    .getReference("root_child")
    .child(firebaseUser.getUid())
    .deleteLastNnRecords();
AL.
  • 36,815
  • 10
  • 142
  • 281
tim4dev
  • 2,846
  • 2
  • 24
  • 30

2 Answers2

1

I would probably use the sort and filter functions.

First, I would grab the children count with a single value listener: https://stackoverflow.com/a/43607203/7949696 , Or in the case of a cloud function I would count the children from the snap on the write trigger.

Then, if childCount > 100, I would OrderByChild() on your timestamp and then filter by LimitToLast(childCount - 100)

If I were you, I would use cloud functions to achieve this and set a function on write to root_child/${uid}/


Edit: Source code link from comments: https://github.com/firebase/functions-samples/tree/master/limit-children

Cheers!


Edit 2: Looks like push() is chronologically sorted, so no need to OrderByChild

James Poag
  • 2,320
  • 1
  • 13
  • 20
  • 1
    Thanks. Looks like this is what I need https://github.com/firebase/functions-samples/tree/master/limit-children – tim4dev May 30 '17 at 11:55
0

Algorithm:

  1. AddListenerForSingleValueEvent is called only 1 time to get all the data and to delete all the old ones
  2. Then we call only addChildEventListener to get only new data

        databaseReference.orderByKey()
            .addListenerForSingleValueEvent(valueEventListener =
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            long count = dataSnapshot.getChildrenCount();
                            long deleteFirst = count - Const.FB_MAX_CHILD;
                            long i = 0;
    
                            Log.i(TAG, "DataSnapshot children count = " + String.valueOf(count));
                            for (DataSnapshot data : dataSnapshot.getChildren()) {
                                i++;
                                if (i <= deleteFirst) {
                                    // delete
                                    Log.i(TAG, "delete => " + data.getKey());
                                    data.getRef().removeValue();
                                } else {
                                    TrackData trackData = data.getValue(TrackData.class);
                                    Log.i(TAG, data.getKey() + " = " + trackData.toString());
                                }
                            }
                        }
    
tim4dev
  • 2,846
  • 2
  • 24
  • 30