aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Source
diff options
context:
space:
mode:
authorGravatar Michael Lehenbauer <mikelehen@gmail.com>2018-04-23 10:03:55 -0700
committerGravatar GitHub <noreply@github.com>2018-04-23 10:03:55 -0700
commite4384c3e809556e75907df74cd116307f397472f (patch)
tree98841eba1d45eb94adcb798b6f792c16ba4b8d18 /Firestore/Source
parent8e70791465f9b5e4bb75dfc18de4a4ed90961974 (diff)
Array Contains Queries (not added to public headers yet). (#1138)
Diffstat (limited to 'Firestore/Source')
-rw-r--r--Firestore/Source/API/FIRQuery+Internal.h35
-rw-r--r--Firestore/Source/API/FIRQuery.mm16
-rw-r--r--Firestore/Source/Core/FSTQuery.h1
-rw-r--r--Firestore/Source/Core/FSTQuery.mm25
-rw-r--r--Firestore/Source/Remote/FSTSerializerBeta.mm4
5 files changed, 76 insertions, 5 deletions
diff --git a/Firestore/Source/API/FIRQuery+Internal.h b/Firestore/Source/API/FIRQuery+Internal.h
index 3c2b2a7..c4f9f23 100644
--- a/Firestore/Source/API/FIRQuery+Internal.h
+++ b/Firestore/Source/API/FIRQuery+Internal.h
@@ -23,7 +23,42 @@ NS_ASSUME_NONNULL_BEGIN
/** Internal FIRQuery API we don't want exposed in our public header files. */
@interface FIRQuery (Internal)
+ (FIRQuery *)referenceWithQuery:(FSTQuery *)query firestore:(FIRFirestore *)firestore;
+
@property(nonatomic, strong, readonly) FSTQuery *query;
+
+@end
+
+// TODO(array-features): Move to FIRQuery.h once backend support is available.
+@interface FIRQuery ()
+
+/**
+ * Creates and returns a new `FIRQuery` with the additional filter that documents must contain
+ * the specified field, it must be an array, and the array must contain the provided value.
+ *
+ * @param field The name of the field containing an array to search
+ * @param value The value that must be contained in the array
+ *
+ * @return The created `FIRQuery`.
+ */
+// clang-format off
+- (FIRQuery *)queryWhereField:(NSString *)field
+ arrayContains:(id)value NS_SWIFT_NAME(whereField(_:arrayContains:));
+// clang-format on
+
+/**
+ * Creates and returns a new `FIRQuery` with the additional filter that documents must contain
+ * the specified field, it must be an array, and the array must contain the provided value.
+ *
+ * @param path The path of the field containing an array to search
+ * @param value The value that must be contained in the array
+ *
+ * @return The created `FIRQuery`.
+ */
+// clang-format off
+- (FIRQuery *)queryWhereFieldPath:(FIRFieldPath *)path
+ arrayContains:(id)value NS_SWIFT_NAME(whereField(_:arrayContains:));
+// clang-format on
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/API/FIRQuery.mm b/Firestore/Source/API/FIRQuery.mm
index 2d78ac0..32d8327 100644
--- a/Firestore/Source/API/FIRQuery.mm
+++ b/Firestore/Source/API/FIRQuery.mm
@@ -238,6 +238,17 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
value:value];
}
+- (FIRQuery *)queryWhereField:(NSString *)field arrayContains:(id)value {
+ return
+ [self queryWithFilterOperator:FSTRelationFilterOperatorArrayContains field:field value:value];
+}
+
+- (FIRQuery *)queryWhereFieldPath:(FIRFieldPath *)path arrayContains:(id)value {
+ return [self queryWithFilterOperator:FSTRelationFilterOperatorArrayContains
+ path:path.internalValue
+ value:value];
+}
+
- (FIRQuery *)queryWhereField:(NSString *)field isGreaterThanOrEqualTo:(id)value {
return [self queryWithFilterOperator:FSTRelationFilterOperatorGreaterThanOrEqual
field:field
@@ -443,6 +454,11 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
value:(id)value {
FSTFieldValue *fieldValue;
if (fieldPath.IsKeyFieldPath()) {
+ if (filterOperator == FSTRelationFilterOperatorArrayContains) {
+ FSTThrowInvalidArgument(
+ @"Invalid query. You can't do arrayContains queries on document ID since document IDs "
+ @"are not arrays.");
+ }
if ([value isKindOfClass:[NSString class]]) {
NSString *documentKey = (NSString *)value;
if ([documentKey containsString:@"/"]) {
diff --git a/Firestore/Source/Core/FSTQuery.h b/Firestore/Source/Core/FSTQuery.h
index 3a67e7f..572fabb 100644
--- a/Firestore/Source/Core/FSTQuery.h
+++ b/Firestore/Source/Core/FSTQuery.h
@@ -34,6 +34,7 @@ typedef NS_ENUM(NSInteger, FSTRelationFilterOperator) {
FSTRelationFilterOperatorEqual,
FSTRelationFilterOperatorGreaterThanOrEqual,
FSTRelationFilterOperatorGreaterThan,
+ FSTRelationFilterOperatorArrayContains,
};
/** Interface used for all query filters. */
diff --git a/Firestore/Source/Core/FSTQuery.mm b/Firestore/Source/Core/FSTQuery.mm
index 8f49c26..0cd11e8 100644
--- a/Firestore/Source/Core/FSTQuery.mm
+++ b/Firestore/Source/Core/FSTQuery.mm
@@ -58,6 +58,8 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
return @">=";
case FSTRelationFilterOperatorGreaterThan:
return @">";
+ case FSTRelationFilterOperatorArrayContains:
+ return @"array_contains";
default:
FSTCFail(@"Unknown FSTRelationFilterOperator %lu", (unsigned long)filterOperator);
}
@@ -119,7 +121,8 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
#pragma mark - Public Methods
- (BOOL)isInequality {
- return self.filterOperator != FSTRelationFilterOperatorEqual;
+ return self.filterOperator != FSTRelationFilterOperatorEqual &&
+ self.filterOperator != FSTRelationFilterOperatorArrayContains;
}
- (const firebase::firestore::model::FieldPath &)field {
@@ -150,6 +153,8 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
if (_field.IsKeyFieldPath()) {
FSTAssert([self.value isKindOfClass:[FSTReferenceValue class]],
@"Comparing on key, but filter value not a FSTReferenceValue.");
+ FSTAssert(self.filterOperator != FSTRelationFilterOperatorArrayContains,
+ @"arrayContains queries don't make sense on document keys.");
FSTReferenceValue *refValue = (FSTReferenceValue *)self.value;
NSComparisonResult comparison = FSTDocumentKeyComparator(document.key, refValue.value);
return [self matchesComparison:comparison];
@@ -180,9 +185,19 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
/** Returns YES if receiver is true with the given value as its LHS. */
- (BOOL)matchesValue:(FSTFieldValue *)other {
- // Only compare types with matching backend order (such as double and int).
- return self.value.typeOrder == other.typeOrder &&
- [self matchesComparison:[other compare:self.value]];
+ if (self.filterOperator == FSTRelationFilterOperatorArrayContains) {
+ if ([other isMemberOfClass:[FSTArrayValue class]]) {
+ FSTArrayValue *arrayValue = (FSTArrayValue *)other;
+ return [arrayValue.internalValue containsObject:self.value];
+ } else {
+ return false;
+ }
+ } else {
+ // Only perform comparison queries on types with matching backend order (such as double and
+ // int).
+ return self.value.typeOrder == other.typeOrder &&
+ [self matchesComparison:[other compare:self.value]];
+ }
}
- (BOOL)matchesComparison:(NSComparisonResult)comparison {
@@ -701,7 +716,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
- (const FieldPath *)inequalityFilterField {
for (id<FSTFilter> filter in self.filters) {
if ([filter isKindOfClass:[FSTRelationFilter class]] &&
- ((FSTRelationFilter *)filter).filterOperator != FSTRelationFilterOperatorEqual) {
+ ((FSTRelationFilter *)filter).isInequality) {
return &filter.field;
}
}
diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm
index ebb49a7..5cbfecc 100644
--- a/Firestore/Source/Remote/FSTSerializerBeta.mm
+++ b/Firestore/Source/Remote/FSTSerializerBeta.mm
@@ -952,6 +952,8 @@ NS_ASSUME_NONNULL_BEGIN
return GCFSStructuredQuery_FieldFilter_Operator_GreaterThanOrEqual;
case FSTRelationFilterOperatorGreaterThan:
return GCFSStructuredQuery_FieldFilter_Operator_GreaterThan;
+ case FSTRelationFilterOperatorArrayContains:
+ return GCFSStructuredQuery_FieldFilter_Operator_ArrayContains;
default:
FSTFail(@"Unhandled FSTRelationFilterOperator: %ld", (long)filterOperator);
}
@@ -970,6 +972,8 @@ NS_ASSUME_NONNULL_BEGIN
return FSTRelationFilterOperatorGreaterThanOrEqual;
case GCFSStructuredQuery_FieldFilter_Operator_GreaterThan:
return FSTRelationFilterOperatorGreaterThan;
+ case GCFSStructuredQuery_FieldFilter_Operator_ArrayContains:
+ return FSTRelationFilterOperatorArrayContains;
default:
FSTFail(@"Unhandled FieldFilter.operator: %d", filterOperator);
}