Skip to content

Commit 148cc77

Browse files
Simplify segment count calculation (#3644)
1 parent 6e788ac commit 148cc77

File tree

3 files changed

+29
-43
lines changed

3 files changed

+29
-43
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteIndexManager.java

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import static java.lang.Math.max;
2424

2525
import android.text.TextUtils;
26-
import android.util.Pair;
2726
import androidx.annotation.Nullable;
2827
import com.google.firebase.Timestamp;
2928
import com.google.firebase.database.collection.ImmutableSortedMap;
@@ -315,13 +314,12 @@ public IndexOffset getMinOffset(String collectionGroup) {
315314
@Override
316315
public IndexType getIndexType(Target target) {
317316
for (Target subTarget : getSubTargets(target)) {
318-
Pair<FieldIndex, Integer> indexAndSegmentCount = getFieldIndexAndSegmentCount(subTarget);
319-
if (indexAndSegmentCount == null) {
317+
FieldIndex index = getFieldIndex(subTarget);
318+
if (index == null) {
320319
return IndexType.NONE;
321320
}
322321

323-
Integer indexSegmentCount = indexAndSegmentCount.second;
324-
if (indexSegmentCount < subTarget.getSegmentCount()) {
322+
if (index.getSegments().size() < subTarget.getSegmentCount()) {
325323
return IndexType.PARTIAL;
326324
}
327325
}
@@ -332,9 +330,9 @@ public IndexType getIndexType(Target target) {
332330
public IndexOffset getMinOffset(Target target) {
333331
List<FieldIndex> fieldIndexes = new ArrayList<>();
334332
for (Target subTarget : getSubTargets(target)) {
335-
Pair<FieldIndex, Integer> indexAndSegmentCount = getFieldIndexAndSegmentCount(subTarget);
336-
if (indexAndSegmentCount != null) {
337-
fieldIndexes.add(indexAndSegmentCount.first);
333+
FieldIndex index = getFieldIndex(subTarget);
334+
if (index != null) {
335+
fieldIndexes.add(index);
338336
}
339337
}
340338
return getMinOffset(fieldIndexes);
@@ -468,12 +466,11 @@ public List<DocumentKey> getDocumentsMatchingTarget(Target target) {
468466
List<Object> bindings = new ArrayList<>();
469467

470468
for (Target subTarget : getSubTargets(target)) {
471-
Pair<FieldIndex, Integer> indexAndSegmentCount = getFieldIndexAndSegmentCount(subTarget);
472-
if (indexAndSegmentCount == null) {
469+
FieldIndex fieldIndex = getFieldIndex(subTarget);
470+
if (fieldIndex == null) {
473471
return null;
474472
}
475473

476-
FieldIndex fieldIndex = indexAndSegmentCount.first;
477474
@Nullable List<Value> arrayValues = subTarget.getArrayValues(fieldIndex);
478475
@Nullable Collection<Value> notInValues = subTarget.getNotInValues(fieldIndex);
479476
@Nullable Bound lowerBound = subTarget.getLowerBound(fieldIndex);
@@ -627,12 +624,11 @@ private Object[] fillBounds(
627624
}
628625

629626
/**
630-
* Returns an index that can be used to serve the provided target, as well as the number of index
631-
* segments that matched the target filters and orderBys. Returns {@code null} if no index is
632-
* configured.
627+
* Returns an index that can be used to serve the provided target. Returns {@code null} if no
628+
* index is configured.
633629
*/
634630
@Nullable
635-
public Pair<FieldIndex, Integer> getFieldIndexAndSegmentCount(Target target) {
631+
private FieldIndex getFieldIndex(Target target) {
636632
hardAssert(started, "IndexManager not started");
637633

638634
TargetIndexMatcher targetIndexMatcher = new TargetIndexMatcher(target);
@@ -647,19 +643,16 @@ public Pair<FieldIndex, Integer> getFieldIndexAndSegmentCount(Target target) {
647643
}
648644

649645
// Return the index with the most number of segments.
650-
int maxNumMatchingSegments = -1;
651646
FieldIndex matchingIndex = null;
652647
for (FieldIndex fieldIndex : collectionIndexes) {
653-
int numMatchingSegments = targetIndexMatcher.servedByIndex(fieldIndex);
654-
if (numMatchingSegments > maxNumMatchingSegments) {
655-
maxNumMatchingSegments = numMatchingSegments;
648+
boolean matches = targetIndexMatcher.servedByIndex(fieldIndex);
649+
if (matches
650+
&& (matchingIndex == null
651+
|| fieldIndex.getSegments().size() > matchingIndex.getSegments().size())) {
656652
matchingIndex = fieldIndex;
657653
}
658654
}
659-
if (maxNumMatchingSegments == -1) {
660-
return null;
661-
}
662-
return new Pair<>(matchingIndex, maxNumMatchingSegments);
655+
return matchingIndex;
663656
}
664657

665658
/**

firebase-firestore/src/main/java/com/google/firebase/firestore/model/TargetIndexMatcher.java

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ public TargetIndexMatcher(Target target) {
111111
}
112112

113113
/**
114-
* Returns the number of index segments that match the TargetIndexMatcher's target. Returns -1 if
115-
* the index cannot be used to serve the target.
114+
* Returns whether the index can be used to serve the TargetIndexMatcher's target.
116115
*
117116
* <p>An index is considered capable of serving the target when:
118117
*
@@ -132,26 +131,21 @@ public TargetIndexMatcher(Target target) {
132131
*
133132
* @throws AssertionError if the index is for a different collection
134133
*/
135-
public int servedByIndex(FieldIndex index) {
134+
public boolean servedByIndex(FieldIndex index) {
136135
hardAssert(index.getCollectionGroup().equals(collectionId), "Collection IDs do not match");
137-
int numMatchingSegments = 0;
138136

139137
// If there is an array element, find a matching filter.
140138
FieldIndex.Segment arraySegment = index.getArraySegment();
141-
if (arraySegment != null) {
142-
if (hasMatchingEqualityFilter(arraySegment)) {
143-
++numMatchingSegments;
144-
} else {
145-
return -1;
146-
}
139+
if (arraySegment != null && !hasMatchingEqualityFilter(arraySegment)) {
140+
return false;
147141
}
148142

149143
Iterator<OrderBy> orderBys = this.orderBys.iterator();
150144
List<FieldIndex.Segment> segments = index.getDirectionalSegments();
151145
int segmentIndex = 0;
152146

153147
// Process all equalities first. Equalities can appear out of order.
154-
for (; segmentIndex < segments.size(); ++segmentIndex, ++numMatchingSegments) {
148+
for (; segmentIndex < segments.size(); ++segmentIndex) {
155149
// We attempt to greedily match all segments to equality filters. If a filter matches an
156150
// index segment, we can mark the segment as used. Since it is not possible to use the same
157151
// field path in both an equality and inequality/oderBy clause, we do not have to consider the
@@ -168,29 +162,28 @@ public int servedByIndex(FieldIndex index) {
168162
// filters and we do not need to map any segments to the target's inequality and orderBy
169163
// clauses.
170164
if (segmentIndex == segments.size()) {
171-
return numMatchingSegments;
165+
return true;
172166
}
173167

174168
// If there is an inequality filter, the next segment must match both the filter and the first
175169
// orderBy clause.
176170
if (inequalityFilter != null) {
177171
FieldIndex.Segment segment = segments.get(segmentIndex);
178172
if (!matchesFilter(inequalityFilter, segment) || !matchesOrderBy(orderBys.next(), segment)) {
179-
return -1;
173+
return false;
180174
}
181175
++segmentIndex;
182-
++numMatchingSegments;
183176
}
184177

185178
// All remaining segments need to represent the prefix of the target's orderBy.
186-
for (; segmentIndex < segments.size(); ++segmentIndex, ++numMatchingSegments) {
179+
for (; segmentIndex < segments.size(); ++segmentIndex) {
187180
FieldIndex.Segment segment = segments.get(segmentIndex);
188181
if (!orderBys.hasNext() || !matchesOrderBy(orderBys.next(), segment)) {
189-
return -1;
182+
return false;
190183
}
191184
}
192185

193-
return numMatchingSegments;
186+
return true;
194187
}
195188

196189
private boolean hasMatchingEqualityFilter(FieldIndex.Segment segment) {

firebase-firestore/src/test/java/com/google/firebase/firestore/model/TargetIndexMatcherTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import static com.google.firebase.firestore.testutil.TestUtil.orderBy;
2222
import static com.google.firebase.firestore.testutil.TestUtil.path;
2323
import static com.google.firebase.firestore.testutil.TestUtil.query;
24-
import static org.junit.Assert.assertEquals;
24+
import static org.junit.Assert.assertFalse;
2525
import static org.junit.Assert.assertTrue;
2626

2727
import com.google.firebase.firestore.core.Query;
@@ -569,13 +569,13 @@ private void validateServesTarget(
569569
Query query, String field, FieldIndex.Segment.Kind kind, Object... fieldsAndKind) {
570570
FieldIndex expectedIndex = fieldIndex("collId", field, kind, fieldsAndKind);
571571
TargetIndexMatcher targetIndexMatcher = new TargetIndexMatcher(query.toTarget());
572-
assertTrue(targetIndexMatcher.servedByIndex(expectedIndex) > 0);
572+
assertTrue(targetIndexMatcher.servedByIndex(expectedIndex));
573573
}
574574

575575
private void validateDoesNotServeTarget(
576576
Query query, String field, FieldIndex.Segment.Kind kind, Object... fieldsAndKind) {
577577
FieldIndex expectedIndex = fieldIndex("collId", field, kind, fieldsAndKind);
578578
TargetIndexMatcher targetIndexMatcher = new TargetIndexMatcher(query.toTarget());
579-
assertEquals(targetIndexMatcher.servedByIndex(expectedIndex), -1);
579+
assertFalse(targetIndexMatcher.servedByIndex(expectedIndex));
580580
}
581581
}

0 commit comments

Comments
 (0)