meteorangular-meteor

Meteor with Angular2 , Fetching all entries from a collection in single shot


I have successfully integeraed meteor with angular2 but while fetching the data from collection facing difficulties in getting at one shot, here is the steps:

Collection Name : OrderDetails No Of records : 1000

Server: Created publication file to subcribe the collection:

Meteor.publish('orderFilter', function() {
         return OrderLineDetails.find({});
   });

Client:

this.dateSubscription = 
     MeteorObservable.subscribe('orderFilter').subscribe(()=> {
        let lines = OrderDetails.find({expectedShipDate:{$in:strArr}},{fields: 
    {"expectedShipDate":1,"loadNo":1},sort:{"expectedShipDate":1}}).fetch();
   });

In this lines attribute fetches all the collection entries, but fails to subscribe for the changes

When I try with below one,

OrderDetails.find({expectedShipDate:{$in:strArr}},{fields:{"expectedShipDate":1,"loadNo":1},sort:{"expectedShipDate":1}}).zone().subscribe(results => {
     // code to loop the results
});

In this am able to subscribe for the collection changes, but the results are looped for 1000 times , as 1000 entries in the colleciton.

Is there any way to get the whole collection entries in one single shot and mean time to subscribe the changes in the collection ?.


Solution

  • Yes, there are a couple of ways you can do it, mostly depending on how you want to handle the data.

    If having everything at once is important, then use a Method such as:

    MeteorObservable.call('getAllElements', (err, result) => {
      // result.length === all elements
    })
    

    While on server side doing

    Meteor.methods({
       getAllElements:function(){return myCollection.find().fetch()}
    })
    

    Now, if you want to listen to changes, ofcourse you'll have to do a subscription, and if you want to lower the amount of subscriptions, use rxjs' debounceTime() function, such as (from your code):

    this.theData.debounceTime(400).subscribe(value => ...., err =>)
    

    This will wait a certain amount of time before subscribing to that collection.

    Now, based on your intent: listening to changes and getting everything at once, you can combine both approaches, not the most efficient but can be effective.

    As @Rager explained, observables are close to streams, so when you populate data on miniMongo (front end collection you use when you find() data and is populated when you subscribe to publications) it will start incrementing until the collection is in sync.

    Since miniMongo is populated when you subscribe to a publication, and not when you query a cursor, you could either:

    1. Try the debouceTime() approach
    2. Use a Meteor.Method after subscribing to the publication, then sync both results, keeping the first response from the method as your starting point, and then using data from Collection.find().subscribe(collectionArray => ..., err=>) to do whatterver you want to do when changes apply (not that recommended, unless you have a specific use case for this)

    Also, .zone() function is specific to force re-render on Angular's event cycle. I'd recomend not use it if you're processing the collections' data instead of rendering it on a ngFor* loop. And if you're using an ngFor* loop, use the async pipe instead ngFor="let entry of Collection | async"