@Test public void valueSelectivity() { List<Filter> highSelectivity = Arrays.asList( filter("high", "==", 0.1), filter("high", "==", 1), filter("high", "==", new Date()), filter("high", "==", "foo"), filter("high", "==", null), filter("high", "==", Double.NaN), filter("high", "==", TestUtil.ref("a/b")), filter("high", "==", new GeoPoint(0.0, 0.0)), filter("high", "==", Blob.fromBytes(new byte[] {}))); List<Filter> lowSelectivity = Arrays.asList( filter("low", "==", true), filter("low", "==", false), filter("low", "==", Arrays.asList("foo", "bar")), filter("low", "==", map("a", "b"))); for (Filter lowSelectivityFilter : lowSelectivity) { Query query = query("a").filter(lowSelectivityFilter); IndexRange indexRange = extractBestIndexRange(query); assertThat(field("low")).isEqualTo(indexRange.getFieldPath()); for (Filter highSelectivityFilter : highSelectivity) { Query modifiedQuery = query.filter(highSelectivityFilter); IndexRange modifiedRange = extractBestIndexRange(modifiedQuery); assertThat(field("high")).isEqualTo(modifiedRange.getFieldPath()); } } }
@Nullable @VisibleForTesting static IndexRange extractBestIndexRange(Query query) { double currentSelectivity = -1; if (!query.getFilters().isEmpty()) { Filter selectedFilter = null; for (Filter currentFilter : query.getFilters()) { double estimatedSelectivity = estimateFilterSelectivity(currentFilter); if (estimatedSelectivity > currentSelectivity) { selectedFilter = currentFilter; currentSelectivity = estimatedSelectivity; } } hardAssert(selectedFilter != null, "Filter should be defined"); return convertFilterToIndexRange(selectedFilter); } else { FieldPath orderPath = query.getOrderBy().get(0).getField(); if (!orderPath.equals(FieldPath.KEY_PATH)) { return IndexRange.builder().setFieldPath(query.getOrderBy().get(0).getField()).build(); } } return null; }
IndexedQueryEngine implements QueryEngine { @Nullable @VisibleForTesting static IndexRange extractBestIndexRange(Query query) { double currentSelectivity = -1; if (!query.getFilters().isEmpty()) { Filter selectedFilter = null; for (Filter currentFilter : query.getFilters()) { double estimatedSelectivity = estimateFilterSelectivity(currentFilter); if (estimatedSelectivity > currentSelectivity) { selectedFilter = currentFilter; currentSelectivity = estimatedSelectivity; } } hardAssert(selectedFilter != null, "Filter should be defined"); return convertFilterToIndexRange(selectedFilter); } else { FieldPath orderPath = query.getOrderBy().get(0).getField(); if (!orderPath.equals(FieldPath.KEY_PATH)) { return IndexRange.builder().setFieldPath(query.getOrderBy().get(0).getField()).build(); } } return null; } }
IndexedQueryEngine implements QueryEngine { @Nullable @VisibleForTesting static IndexRange extractBestIndexRange(Query query) { double currentSelectivity = -1; if (!query.getFilters().isEmpty()) { Filter selectedFilter = null; for (Filter currentFilter : query.getFilters()) { double estimatedSelectivity = estimateFilterSelectivity(currentFilter); if (estimatedSelectivity > currentSelectivity) { selectedFilter = currentFilter; currentSelectivity = estimatedSelectivity; } } hardAssert(selectedFilter != null, "Filter should be defined"); return convertFilterToIndexRange(selectedFilter); } else { FieldPath orderPath = query.getOrderBy().get(0).getField(); if (!orderPath.equals(FieldPath.KEY_PATH)) { return IndexRange.builder().setFieldPath(query.getOrderBy().get(0).getField()).build(); } } return null; } IndexedQueryEngine(SQLiteCollectionIndex collectionIndex); }
IndexedQueryEngine implements QueryEngine { @Nullable @VisibleForTesting static IndexRange extractBestIndexRange(Query query) { double currentSelectivity = -1; if (!query.getFilters().isEmpty()) { Filter selectedFilter = null; for (Filter currentFilter : query.getFilters()) { double estimatedSelectivity = estimateFilterSelectivity(currentFilter); if (estimatedSelectivity > currentSelectivity) { selectedFilter = currentFilter; currentSelectivity = estimatedSelectivity; } } hardAssert(selectedFilter != null, "Filter should be defined"); return convertFilterToIndexRange(selectedFilter); } else { FieldPath orderPath = query.getOrderBy().get(0).getField(); if (!orderPath.equals(FieldPath.KEY_PATH)) { return IndexRange.builder().setFieldPath(query.getOrderBy().get(0).getField()).build(); } } return null; } IndexedQueryEngine(SQLiteCollectionIndex collectionIndex); @Override void setLocalDocumentsView(LocalDocumentsView localDocuments); @Override ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
      Query query,
      SnapshotVersion lastLimboFreeSnapshotVersion,
      ImmutableSortedSet<DocumentKey> remoteKeys); @Override void handleDocumentChange(MaybeDocument oldDocument, MaybeDocument newDocument); }
IndexedQueryEngine implements QueryEngine { @Nullable @VisibleForTesting static IndexRange extractBestIndexRange(Query query) { double currentSelectivity = -1; if (!query.getFilters().isEmpty()) { Filter selectedFilter = null; for (Filter currentFilter : query.getFilters()) { double estimatedSelectivity = estimateFilterSelectivity(currentFilter); if (estimatedSelectivity > currentSelectivity) { selectedFilter = currentFilter; currentSelectivity = estimatedSelectivity; } } hardAssert(selectedFilter != null, "Filter should be defined"); return convertFilterToIndexRange(selectedFilter); } else { FieldPath orderPath = query.getOrderBy().get(0).getField(); if (!orderPath.equals(FieldPath.KEY_PATH)) { return IndexRange.builder().setFieldPath(query.getOrderBy().get(0).getField()).build(); } } return null; } IndexedQueryEngine(SQLiteCollectionIndex collectionIndex); @Override void setLocalDocumentsView(LocalDocumentsView localDocuments); @Override ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
      Query query,
      SnapshotVersion lastLimboFreeSnapshotVersion,
      ImmutableSortedSet<DocumentKey> remoteKeys); @Override void handleDocumentChange(MaybeDocument oldDocument, MaybeDocument newDocument);  }