@@ -70,8 +70,12 @@ - (nullable FSTMaybeDocument *)documentForKey:(const DocumentKey &)key {
70
70
// Internal version of documentForKey: which allows reusing `batches`.
71
71
- (nullable FSTMaybeDocument *)documentForKey : (const DocumentKey &)key
72
72
inBatches : (NSArray <FSTMutationBatch *> *)batches {
73
- FSTMaybeDocument *_Nullable remoteDoc = [self .remoteDocumentCache entryForKey: key];
74
- return [self localDocument: remoteDoc key: key inBatches: batches];
73
+ FSTMaybeDocument *_Nullable document = [self .remoteDocumentCache entryForKey: key];
74
+ for (FSTMutationBatch *batch in batches) {
75
+ document = [batch applyTo: document documentKey: key];
76
+ }
77
+
78
+ return document;
75
79
}
76
80
77
81
- (FSTMaybeDocumentDictionary *)documentsForKeys : (const DocumentKeySet &)keys {
@@ -110,37 +114,34 @@ - (FSTDocumentDictionary *)documentsMatchingDocumentQuery:(const ResourcePath &)
110
114
}
111
115
112
116
- (FSTDocumentDictionary *)documentsMatchingCollectionQuery : (FSTQuery *)query {
113
- // Query the remote documents and overlay mutations.
114
- // TODO(mikelehen): There may be significant overlap between the mutations affecting these
115
- // remote documents and the allMutationBatchesAffectingQuery mutations. Consider optimizing.
116
117
__block FSTDocumentDictionary *results = [self .remoteDocumentCache documentsMatchingQuery: query];
117
- results = [self localDocuments: results];
118
-
119
- // Now use the mutation queue to discover any other documents that may match the query after
120
- // applying mutations.
121
- DocumentKeySet matchingKeys;
122
- NSArray <FSTMutationBatch *> *matchingMutationBatches =
118
+ // Get locally persisted mutation batches.
119
+ NSArray <FSTMutationBatch *> *matchingBatches =
123
120
[self .mutationQueue allMutationBatchesAffectingQuery: query];
124
- for (FSTMutationBatch *batch in matchingMutationBatches) {
121
+
122
+ for (FSTMutationBatch *batch in matchingBatches) {
125
123
for (FSTMutation *mutation in batch.mutations ) {
126
- // TODO(mikelehen): PERF: Check if this mutation actually affects the query to reduce work.
124
+ // Only process documents belonging to the collection.
125
+ if (!query.path .IsImmediateParentOf (mutation.key .path ())) {
126
+ continue ;
127
+ }
127
128
128
- // If the key is already in the results, we can skip it.
129
- if (![results containsKey: mutation.key]) {
130
- matchingKeys = matchingKeys.insert (mutation.key );
129
+ FSTDocumentKey *key = static_cast <FSTDocumentKey *>(mutation.key );
130
+ // baseDoc may be nil for the documents that weren't yet written to the backend.
131
+ FSTMaybeDocument *baseDoc = results[key];
132
+ FSTMaybeDocument *mutatedDoc =
133
+ [mutation applyTo: baseDoc baseDocument: baseDoc localWriteTime: batch.localWriteTime];
134
+
135
+ if ([mutatedDoc isKindOfClass: [FSTDeletedDocument class ]]) {
136
+ results = [results dictionaryByRemovingObjectForKey: key];
137
+ } else if ([mutatedDoc isKindOfClass: [FSTDocument class ]]) {
138
+ results = [results dictionaryBySettingObject: (FSTDocument *)mutatedDoc forKey: key];
139
+ } else {
140
+ HARD_FAIL (" Unknown document: %s" , mutatedDoc);
131
141
}
132
142
}
133
143
}
134
144
135
- // Now add in results for the matchingKeys.
136
- FSTMaybeDocumentDictionary *matchingKeysDocs = [self documentsForKeys: matchingKeys];
137
- [matchingKeysDocs
138
- enumerateKeysAndObjectsUsingBlock: ^(FSTDocumentKey *key, FSTMaybeDocument *doc, BOOL *stop) {
139
- if ([doc isKindOfClass: [FSTDocument class ]]) {
140
- results = [results dictionaryBySettingObject: (FSTDocument *)doc forKey: key];
141
- }
142
- }];
143
-
144
145
// Finally, filter out any documents that don't actually match the query. Note that the extra
145
146
// reference here prevents ARC from deallocating the initial unfiltered results while we're
146
147
// enumerating them.
@@ -155,54 +156,6 @@ - (FSTDocumentDictionary *)documentsMatchingCollectionQuery:(FSTQuery *)query {
155
156
return results;
156
157
}
157
158
158
- /* *
159
- * Takes a remote document and applies local mutations to generate the local view of the
160
- * document.
161
- *
162
- * @param document The base remote document to apply mutations to.
163
- * @param documentKey The key of the document (necessary when remoteDocument is nil).
164
- */
165
- - (nullable FSTMaybeDocument *)localDocument : (nullable FSTMaybeDocument *)document
166
- key : (const DocumentKey &)documentKey
167
- inBatches : (NSArray <FSTMutationBatch *> *)batches {
168
- for (FSTMutationBatch *batch in batches) {
169
- document = [batch applyTo: document documentKey: documentKey];
170
- }
171
-
172
- return document;
173
- }
174
-
175
- /* *
176
- * Takes a set of remote documents and applies local mutations to generate the local view of
177
- * the documents.
178
- *
179
- * @param documents The base remote documents to apply mutations to.
180
- * @return The local view of the documents.
181
- */
182
- - (FSTDocumentDictionary *)localDocuments : (FSTDocumentDictionary *)documents {
183
- __block DocumentKeySet keySet;
184
- [documents
185
- enumerateKeysAndObjectsUsingBlock: ^(FSTDocumentKey *key, FSTDocument *doc, BOOL *stop) {
186
- keySet = keySet.insert (doc.key );
187
- }];
188
- NSArray <FSTMutationBatch *> *batches =
189
- [self .mutationQueue allMutationBatchesAffectingDocumentKeys: keySet];
190
-
191
- __block FSTDocumentDictionary *result = documents;
192
- [documents enumerateKeysAndObjectsUsingBlock: ^(FSTDocumentKey *key, FSTDocument *remoteDocument,
193
- BOOL *stop) {
194
- FSTMaybeDocument *mutatedDoc = [self localDocument: remoteDocument key: key inBatches: batches];
195
- if ([mutatedDoc isKindOfClass: [FSTDeletedDocument class ]]) {
196
- result = [result dictionaryByRemovingObjectForKey: key];
197
- } else if ([mutatedDoc isKindOfClass: [FSTDocument class ]]) {
198
- result = [result dictionaryBySettingObject: (FSTDocument *)mutatedDoc forKey: key];
199
- } else {
200
- HARD_FAIL (" Unknown document: %s" , mutatedDoc);
201
- }
202
- }];
203
- return result;
204
- }
205
-
206
159
@end
207
160
208
161
NS_ASSUME_NONNULL_END
0 commit comments