diff --git a/src/rx-query.ts b/src/rx-query.ts index c43cba83e1c..24e6456a5aa 100644 --- a/src/rx-query.ts +++ b/src/rx-query.ts @@ -576,14 +576,28 @@ export class RxQueryBase< ); for (const changedDoc of changedDocs) { - /* - * no need to fetch again, we already got the doc from the list of changed docs, and therefore we filter - * deleted docs as well - */ - persistedQueryCacheIds.delete(changedDoc[primaryPath] as string); + const docWasInOldPersistedResults = persistedQueryCacheIds.has(changedDoc[primaryPath] as string); + const docMatchesNow = this.doesDocumentDataMatch(changedDoc); + + if (docWasInOldPersistedResults && !docMatchesNow && this.mangoQuery.limit) { + // Unfortunately if any doc was removed from the results since the last result, + // there is no way for us to be sure our calculated results are correct. + // So we should simply give up and re-exec the query. + this._persistentQueryCacheResult = value ?? undefined; + this._persistentQueryCacheResultLwt = lwt ?? undefined; + return; + } + + if (docWasInOldPersistedResults) { + /* + * no need to fetch again, we already got the doc from the list of changed docs, and therefore we filter + * deleted docs as well + */ + persistedQueryCacheIds.delete(changedDoc[primaryPath] as string); + } // ignore deleted docs or docs that do not match the query - if (!this.doesDocumentDataMatch(changedDoc)) { + if (!docMatchesNow) { continue; } diff --git a/test/unit/rx-query.test.ts b/test/unit/rx-query.test.ts index e8a831d862b..35e0ea06ae9 100644 --- a/test/unit/rx-query.test.ts +++ b/test/unit/rx-query.test.ts @@ -1831,7 +1831,7 @@ describe('rx-query.test.ts', () => { collection.database.destroy(); }); - it.skip('gives correct limit results when items were removed', async () => { + it('gives correct limit results when items were removed', async () => { const {collection} = await setUpPersistentQueryCacheCollection(); const human1 = schemaObjects.human('1', 30); const human2 = schemaObjects.human('2', 40); @@ -1865,10 +1865,14 @@ describe('rx-query.test.ts', () => { // now when we create the query again, it has no way of knowing how to fill the missing item const queryAgain = collection.find({ limit: 2, sort: [{age: 'asc'}], selector: { age: { $gt: 10 } } }); + assert.strictEqual(queryAgain._execOverDatabaseCount, 0); + await queryAgain.enablePersistentQueryCache(cache); const updatedResults = await queryAgain.exec(); - assert.deepStrictEqual(updatedResults.map(h => h.passportId), ['2', '3']); + // We must re-exec the query to make it correct. + assert.strictEqual(queryAgain._execOverDatabaseCount, 1); + assert.deepStrictEqual(updatedResults.map(h => h.passportId), ['2', '3']); collection.database.destroy(); }); });