[firestore] Correctly support dates, geopoints, DocumentSnapshots and other types in startAt, startAfter, etc

This commit is contained in:
Chris Bianca
2017-10-31 22:18:07 +00:00
parent 6ae0049338
commit 270279551a
8 changed files with 102 additions and 42 deletions

View File

@@ -236,7 +236,7 @@ public class FirestoreSerialize {
return map;
}
private static List<Object> parseReadableArray(FirebaseFirestore firestore, ReadableArray readableArray) {
static List<Object> parseReadableArray(FirebaseFirestore firestore, ReadableArray readableArray) {
List<Object> list = new ArrayList<>();
if (readableArray != null) {
for (int i = 0; i < readableArray.size(); i++) {
@@ -246,7 +246,7 @@ public class FirestoreSerialize {
return list;
}
public static Object parseTypeMap(FirebaseFirestore firestore, ReadableMap typeMap) {
static Object parseTypeMap(FirebaseFirestore firestore, ReadableMap typeMap) {
String type = typeMap.getString("type");
if ("boolean".equals(type)) {
return typeMap.getBoolean("value");

View File

@@ -120,7 +120,7 @@ public class RNFirebaseFirestoreCollectionReference {
Query query = firestore.collection(path);
query = applyFilters(firestore, query);
query = applyOrders(query);
query = applyOptions(query);
query = applyOptions(firestore, query);
return query;
}
@@ -166,14 +166,14 @@ public class RNFirebaseFirestoreCollectionReference {
return query;
}
private Query applyOptions(Query query) {
private Query applyOptions(FirebaseFirestore firestore, Query query) {
if (options.hasKey("endAt")) {
ReadableArray endAtArray = options.getArray("endAt");
query = query.endAt(Utils.recursivelyDeconstructReadableArray(endAtArray));
List<Object> endAtList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endAt"));
query = query.endAt(endAtList.toArray());
}
if (options.hasKey("endBefore")) {
ReadableArray endBeforeArray = options.getArray("endBefore");
query = query.endBefore(Utils.recursivelyDeconstructReadableArray(endBeforeArray));
List<Object> endBeforeList = FirestoreSerialize.parseReadableArray(firestore, options.getArray("endBefore"));
query = query.endBefore(endBeforeList.toArray());
}
if (options.hasKey("limit")) {
int limit = options.getInt("limit");
@@ -186,12 +186,12 @@ public class RNFirebaseFirestoreCollectionReference {
// Android doesn't support selectFields
}
if (options.hasKey("startAfter")) {
ReadableArray startAfterArray = options.getArray("startAfter");
query = query.startAfter(Utils.recursivelyDeconstructReadableArray(startAfterArray));
List<Object> startAfterList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAfter"));
query = query.startAfter(startAfterList.toArray());
}
if (options.hasKey("startAt")) {
ReadableArray startAtArray = options.getArray("startAt");
query = query.startAt(Utils.recursivelyDeconstructReadableArray(startAtArray));
List<Object> startAtList= FirestoreSerialize.parseReadableArray(firestore, options.getArray("startAt"));
query = query.startAt(startAtList.toArray());
}
return query;
}

View File

@@ -85,7 +85,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
FIRQuery *query = (FIRQuery*)[firestore collectionWithPath:_path];
query = [self applyFilters:firestore query:query];
query = [self applyOrders:query];
query = [self applyOptions:query];
query = [self applyOptions:firestore query:query];
return query;
}
@@ -123,12 +123,13 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
return query;
}
- (FIRQuery *)applyOptions:(FIRQuery *) query {
- (FIRQuery *)applyOptions:(FIRFirestore *) firestore
query:(FIRQuery *) query {
if (_options[@"endAt"]) {
query = [query queryEndingAtValues:_options[@"endAt"]];
query = [query queryEndingAtValues:[RNFirebaseFirestoreDocumentReference parseJSArray:firestore jsArray:_options[@"endAt"]]];
}
if (_options[@"endBefore"]) {
query = [query queryEndingBeforeValues:_options[@"endBefore"]];
query = [query queryEndingBeforeValues:[RNFirebaseFirestoreDocumentReference parseJSArray:firestore jsArray:_options[@"endBefore"]]];
}
if (_options[@"limit"]) {
query = [query queryLimitedTo:[_options[@"limit"] intValue]];
@@ -140,10 +141,10 @@ queryListenOptions:(NSDictionary *) queryListenOptions {
// iOS doesn't support selectFields
}
if (_options[@"startAfter"]) {
query = [query queryStartingAfterValues:_options[@"startAfter"]];
query = [query queryStartingAfterValues:[RNFirebaseFirestoreDocumentReference parseJSArray:firestore jsArray:_options[@"startAfter"]]];
}
if (_options[@"startAt"]) {
query = [query queryStartingAtValues:_options[@"startAt"]];
query = [query queryStartingAtValues:[RNFirebaseFirestoreDocumentReference parseJSArray:firestore jsArray:_options[@"startAt"]]];
}
return query;
}

View File

@@ -26,8 +26,10 @@
- (void)update:(NSDictionary *)data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject;
- (BOOL)hasListeners;
+ (NSDictionary *)snapshotToDictionary:(FIRDocumentSnapshot *)documentSnapshot;
+(NSDictionary *)parseJSMap:(FIRFirestore *) firestore jsMap:(NSDictionary *) jsMap;
+(id)parseJSTypeMap:(FIRFirestore *) firestore jsTypeMap:(NSDictionary *) jsTypeMap;
+ (NSDictionary *)parseJSMap:(FIRFirestore *) firestore jsMap:(NSDictionary *) jsMap;
+ (NSArray *)parseJSArray:(FIRFirestore *) firestore jsArray:(NSArray *) jsArray;
+ (id)parseJSTypeMap:(FIRFirestore *) firestore jsTypeMap:(NSDictionary *) jsTypeMap;
@end
#else

View File

@@ -83,10 +83,6 @@ export default class CollectionReference {
return this._query.orderBy(fieldPath, directionStr);
}
select(varArgs: string[]): Query {
return this._query.select(varArgs);
}
startAfter(fieldValues: any): Query {
return this._query.startAfter(fieldValues);
}

View File

@@ -5,7 +5,7 @@
import DocumentSnapshot from './DocumentSnapshot';
import Path from './Path';
import QuerySnapshot from './QuerySnapshot';
import { buildTypeMap } from './utils/serialize';
import { buildNativeArray, buildTypeMap } from './utils/serialize';
import { firestoreAutoId, isFunction, isObject } from '../../utils';
const DIRECTIONS = {
@@ -78,24 +78,20 @@ export default class Query {
return this._firestore;
}
endAt(fieldValues: any): Query {
fieldValues = [].slice.call(arguments);
// TODO: Validation
endAt(...snapshotOrVarArgs: any): Query {
const options = {
...this._queryOptions,
endAt: fieldValues,
endAt: this._buildOrderByOption(snapshotOrVarArgs),
};
return new Query(this.firestore, this._referencePath, this._fieldFilters,
this._fieldOrders, options);
}
endBefore(fieldValues: any): Query {
fieldValues = [].slice.call(arguments);
// TODO: Validation
endBefore(...snapshotOrVarArgs: any): Query {
const options = {
...this._queryOptions,
endBefore: fieldValues,
endBefore: this._buildOrderByOption(snapshotOrVarArgs),
};
return new Query(this.firestore, this._referencePath, this._fieldFilters,
@@ -234,24 +230,20 @@ export default class Query {
combinedOrders, this._queryOptions);
}
startAfter(fieldValues: any): Query {
fieldValues = [].slice.call(arguments);
// TODO: Validation
startAfter(...snapshotOrVarArgs: any): Query {
const options = {
...this._queryOptions,
startAfter: fieldValues,
startAfter: this._buildOrderByOption(snapshotOrVarArgs),
};
return new Query(this.firestore, this._referencePath, this._fieldFilters,
this._fieldOrders, options);
}
startAt(fieldValues: any): Query {
fieldValues = [].slice.call(arguments);
// TODO: Validation
startAt(...snapshotOrVarArgs: any): Query {
const options = {
...this._queryOptions,
startAt: fieldValues,
startAt: this._buildOrderByOption(snapshotOrVarArgs),
};
return new Query(this.firestore, this._referencePath, this._fieldFilters,
@@ -277,6 +269,23 @@ export default class Query {
* INTERNALS
*/
_buildOrderByOption(snapshotOrVarArgs: any[]) {
// TODO: Validation
let values;
if (snapshotOrVarArgs.length === 1 && snapshotOrVarArgs[0] instanceof DocumentSnapshot) {
const docSnapshot = snapshotOrVarArgs[0];
values = [];
for (let i = 0; i < this._fieldOrders.length; i++) {
const fieldOrder = this._fieldOrders[i];
values.push(docSnapshot.get(fieldOrder.fieldPath));
}
} else {
values = snapshotOrVarArgs;
}
return buildNativeArray(values);
}
/**
* Remove query snapshot listener
* @param listener

View File

@@ -27,7 +27,7 @@ export const buildNativeMap = (data: Object): Object => {
return nativeData;
};
const buildNativeArray = (array: Object[]): any[] => {
export const buildNativeArray = (array: Object[]): any[] => {
const nativeArray = [];
if (array) {
array.forEach((value) => {

View File

@@ -569,6 +569,19 @@ function collectionReferenceTests({ describe, it, context, firebase, before, aft
);
});
});
it('handles snapshots', async () => {
const collectionSnapshot = await collectionTests.orderBy('foo').get();
return collectionTests.orderBy('foo').endAt(collectionSnapshot.docs[2])
.get()
.then((querySnapshot) => {
should.equal(querySnapshot.size, 3);
should.deepEqual(
querySnapshot.docs.map(doc => doc.data().daz),
[123, 234, 345],
);
});
});
});
context('endBefore', () => {
@@ -607,6 +620,19 @@ function collectionReferenceTests({ describe, it, context, firebase, before, aft
);
});
});
it('handles snapshots', async () => {
const collectionSnapshot = await collectionTests.orderBy('foo').get();
return collectionTests.orderBy('foo').endBefore(collectionSnapshot.docs[2])
.get()
.then((querySnapshot) => {
should.equal(querySnapshot.size, 2);
should.deepEqual(
querySnapshot.docs.map(doc => doc.data().daz),
[123, 234],
);
});
});
});
context('startAt', () => {
@@ -645,6 +671,19 @@ function collectionReferenceTests({ describe, it, context, firebase, before, aft
);
});
});
it('handles snapshots', async () => {
const collectionSnapshot = await collectionTests.orderBy('foo').get();
return collectionTests.orderBy('foo').startAt(collectionSnapshot.docs[2])
.get()
.then((querySnapshot) => {
should.equal(querySnapshot.size, 3);
should.deepEqual(
querySnapshot.docs.map(doc => doc.data().daz),
[345, 456, 567],
);
});
});
});
context('startAfter', () => {
@@ -683,6 +722,19 @@ function collectionReferenceTests({ describe, it, context, firebase, before, aft
);
});
});
it('handles snapshot', async () => {
const collectionSnapshot = await collectionTests.orderBy('foo').get();
return collectionTests.orderBy('foo').startAfter(collectionSnapshot.docs[2])
.get()
.then((querySnapshot) => {
should.equal(querySnapshot.size, 2);
should.deepEqual(
querySnapshot.docs.map(doc => doc.data().daz),
[456, 567],
);
});
});
});
after(() => {