how not to trigger event child_added for initial children - firebase

I have rather big data-set, possibly millions of objects and I need to trigger the child_added event and get the last added child. However whenever I start the service it triggers the event once for each initial child in the data-set.
How Can I avoid this behavior?
edit:
The suggested solution does not solve the problem - it is just ignoring it in my opinion. In my specific case I store the unique reference to other object as a name and it's value is other important data. The Priority on the record is set to the specific number in my case time stamp. I use this to retrieve the record to build a timeline so I need the option to save a new object with custom timestamp - not only current. Listener .on() on event child_added fits the need perfectly except fetching all the children upon the start. This in my opinion renders this feature absolutely pointless on any large collection.

You could use limit(1). Then the listener will fire once at the beginning, and then again each time a new child is added.
fireRef.limit(1).on('child_added', function() { /*code*/ });

Related

How to delete records from a model referenced by a different model?

I have two models, where model A references items in model B. When I delete items from model B, react rerenders before I can update model A to also delete the referenced items.
Example:
I have a feed. The feed is made up of different types of items. Each type of item is stored in its respective model.
The feed order is stored as an array of item IDs, referencing the items in their different substores.
I have made a minimal failing example here. The issue occurs after clicking the button three times
https://codesandbox.io/s/deleting-referenced-items-kmw1e
The key line is
else console.error(">>>> feed order contains deleted item", id);
It's problematic that the feed order might contain deleted items because it could mean there is a programming error that resulted in bad references. In this case it's not a programming error, the second store just hasn't updated yet.
Is there a way I might be able to batch the createAndDeleteTodo, to not evaluate all listeners until the entire thunk and all subthunks have completed?
In the above example it's trivial enough to just have one master action which updates the feed order and the items but it would feel cumbersome if there was more than just one type of item as each item type lives in it's own respective model.
The same thunk action is triggering multiple Actions. And as per the definition of useStoreState:
The useStoreState will execute any time an update to your store's state occurs
So, in effect, when you do this inside the thunk:
actions.setTodos({ newTodos: [newTodo], todoToDelete });
actions.updateFeedOrder({ newTodos: [newTodo], todoToDelete });
there are two actions being dispatched and those would account for a separate store state change event listener. You will get multiple render calls for the multiple store updates.
You have two options:
Either club those actions into one as shown in the example: https://codesandbox.io/s/so-deleting-referenced-items-forked-x4d7v
OR check the useStoreState method for a case on handling the render only when both the store values are matching the count
It seems the problem is that you're dispatching to redux store 2 times. First when you create new items and then when you delete them.
I'd suggest to do it this way:
Create a deep copy of object/array you wanna work with.
Make both operations on that copy.
Dispatch that value to the store.
This way nothing will be rerendered until both operations are finished.

Can we trigger firebase cloud functions when we create a collection (not "document")?

I am trying to achieve a scenario where firebase triggers only once when a collection is created and not every time that a document is added to the collection. Let's say I want it to trigger only for the first document added to the collection and not for every other document added to the same collection. How can that be done? Please help !!!
There is no such trigger for Cloud Functions. Your trigger path must specify exactly one document, or use wildcards to specify a path that could possibly match many documents.
If you want to know what a collection contains its first document, you will have to either:
Maintain a count of documents in that collection (perhaps in yet another document in another collection), and trigger of the change of that value when it goes from 0 to 1.
Query all of the documents in the collection where a document was just created in order to figure out if it was the first one.
Both of these requires a fair amount of extra code - very much not trivial to implement correctly for arbitrary collections. They could also run into problems under heavy load. If these options won't work for you, I suggest figuring out another way to get you function to trigger at the right time.
While It's not possible to do directly. You can check if collection contains any elements, and if it does it means that it exists.
const result =await firestore.collection("collection").limit(1).get()
if(result.size){
// Collection exists
}

Meteor UX Issue: After adding item to a sorted list, the item is added to the top and then sorted

I am creating a basic chat with Meteor.
On the client I do:
div.chat-discussion
each messages
+chatMessage
The helper is
Messages.find
conversationId: t.data.conversation._id
,
sort:
createdAt: 1
So I am sorting the chat message in order from oldest first to newest last.
The chat looks like this
But whenever I send a message, it isn't added directly to the bottom.
It is added to the top for a few milliseconds and then shifted to the bottom.
It makes the UX feel glitchy. Why is this happening, and how can I fix this?
UPDATE
I seemed to have fixed the issue by removing the sort and just returning the messages in the helpers like
Messages.find
conversationId: t.data.conversation._id
So if I don't sort client side, the message is added to the bottom of the message list automatically without flashing. I am not sure how or why. I guess by default it is sorted in order of oldest first.
There is no default sort on a collection other than FIFO which means as long as you do not sort, the records are send as they were written.
If you just have continously messages, this may fit your needs, but when you are in sync / offline situations sometimes, you might get the list not as it is when time sorted.
I guess you are using autopublish on server?
You should write your own server publish method and return the sorted list already from server.
So on client you may subscribe then just by find() or do also the sort on mini-mongo (preferred)
This should prevent glitchy UX
Cheers
I figured out what was happening.
The problem in the end was a conflict with the sorting I was using and how the timestampable (https://atmospherejs.com/zimme/collection-timestampable) package adds the createdAt field.
I was sorting on the client by the field createdAt, which is added by the timestampable package. The issue is that the field doesn't exist when the document is first inserted, so that is why I saw the message append to the top of the list and when the createdAt field got added right after, then it jumped down to its sort position.
To fix this I am adding a field called sentAt upon insertion, and now also sorting by that field.
This fixed the issue. I was trying to sort by a field that did not exist upon insertion. This will show itself in the UI even if the field is added right after insertion.

How to completely delete recurring event instance?

If you create a recurring event in google calendar, you actually create one single event (parent) with recurrence rule, others are just virtually added. Once you move any of those virtuals, it gets saved as instance and you can edit it in any way you like without affecting the parent event itself.
If you edit that instance to match its parent, it gets deleted and replaced with the virtual one once again. (No need to keep instance which is no different from the parent event, right?)
I'm doing the same in my application. However, when I'm trying to do so using google-php-api-client, the only option to delete something, is to set the event status as 'cancelled' which will make the instance deleted.
My question is:
How to delete (or reset) the instances without the need of updating them one by one to match its parent?
EDIT: Forgot to mention why do I need this and what am I trying to achieve.
Basically, if you edit an instance, Google will ask you whether you want to edit "Only this", "Following", or "All" of the recurring events. If you select "Following", google will throw away everything related to the parent event from this date (where original_start > date), modify its rule to set UNTIL rule with the date of instance being edited and pass its old rule to newly created event with starting time same as the date of this particular instance.
Since I know of no method, how to delete multiple events matching some condition. The only way I could figure this out, is to select all of those, and update them one by one, which could be a bit of problem since you can:
Create recurring event with recurrence-end unspecified
Decide to modify all following events

Meteor pagination: cursor fetch limit with getmore

I have an infinite scroll page where I'm not using Meteor templates to draw the items. The reason for that belongs in a whole other thread. I'm trying to figure out how to paginate the data without fetching all the items at once. I have an idea about using a limit on the cursor, but can't find any real samples online of the proper way to do this.
Should the server call return the cursor itself or just the find with limited data set? If the server doesn't return the cursor itself, won't I lose position when I try to fetch the next set of results?
Also, I want to make sure to retrieve data from the same cursor. Like if there are currently 100 items and I fetch 20, I expect the next 4 fetches to get 20-40, 40-60, 60-80, and 80-100. If in the interim some items got inserted or deleted, I don't want it to mess up the fetches. I am handling reactivity separately and letting users decide when to update the items (which should reset the cursor).
Help/advice appreciated!
What you would usually do is this:
var cursor = collection.find({},{limit:100+20*page});
The first {} is obviously the selector!
Docs:
http://docs.meteor.com/#/basic/Mongo-Collection-find
You don't have to worry about returning only the values 100-120 and then 120-140 etc. since meteors ddp does that for you!
If you were using meteor's blas or you just want to have the reactivity, you should probably store the page variable in the Session or create a dependancy:
https://manual.meteor.com/#deps-asimpleexample

Resources