Minimongo update from Method results leads to Error on subscriptions

#1

I receive Documents from the Server due to performance reasons via Methods:

Meteor.methods({
  getDocs() {
    return MyCollection.find({ ... }).fetch()
  }
})

On the client I store them inside the local-collection:

const LocalCollection = MyCollection._collection
Meteor.call('getDocs', { ... }, (err, docs) => {
  docs.forEach(doc => LocalCollection.insert(doc))
})

Now this works fine but when I run a subscription at another point that also returns documents, that were among those, returned by the method, I receive the following error:

Uncaught Error: Expected not to find a document already present for an add

My question is, whether to flush the Localcollection before the subscription manually or if there is a way to just tell it to “override the existing docs, no matter what”?

#2

you have to make a local collection:

const LocalCollection = new Meteor.Collection(null);
1 Like
#3

I would like to avoid managing an additional collection for the docs loaded by the Methods, which is why
I am using the LocalCollection underlying to the Collection (via MyCollection._collection).

It is just that I am loading parts of the same collection via Method and others via subscription and in rare cases these sets overlap for one or two documents and the error is thrown.

I thought maybe I can manipulate the behavior so I can manage all docs in the same Client collection.

Edit: I forgot to mention in the main post, that I use the LocalCollection because

Meteor.call('getDocs', { ... }, (err, docs) => {
  docs.forEach(doc => MyCollection.insert(doc))
})

denies to insert the documents because I have allow/deny set to deny for all by default. Maybe there is a better solution by completely removing allow/deny (is that even possible)?

#4

The problem is that when you subscribe, the server isn’t aware that you have those documents, so sends them to you as new documents.

You could manually update the publication context for the requesting connection, but its likely that whatever performance improvement you saw by switching to methods would be largely reduced if you do this.

You could also switch your publication to a more manual method, and thus a lighter weight check of the documents you have manually fetched - but this is not trivial to implement and has its own performance cost.

The third option is to override the mechanism on the client that complains about this behaviour to simply update the present document, I’m not sure this is possible either without largely re-writing the connection code.

In short - your three other options are way worse than just using a local collection to begin with :slight_smile: you could switch all your client side code to use the LocalCollection rather than MyCollection, then you could have a global autorun block that pulls documents from MyCollection and inserts them into LocalCollection that way on the client you still only have one source for your documents, but they are populated from subscriptions and method calls.

#5

Perhaps you could explain?

You clearly are also using pub/sub if you’re getting conflicts, so why complicate things in this way?

#6

The documents I load are denormalized inside the method, because they are referencing many other documents:

{
  title: 'some title'
  a: [...],
  b: [...],
  c: [...],
  d: [...]
}

I would otherwise require to 4 pub/sub although the data does not needed to be reactive. However, I would still like to access the data using Minimongo instead of Array processing. (Maybe this is just my laziness.)

The publication is to get all document titles and see the most recent added docs.