/** * Target the given field in the range predicate. * <p> * Multiple fields may be targeted by the same predicate: * the predicate will match if <em>any</em> targeted field matches. * <p> * When targeting multiple fields, those fields must have compatible types. * See <a href="SearchPredicateFactoryContext.html#commonconcepts-parametertype">there</a> for more information. * * @param absoluteFieldPath The absolute path (from the document root) of the targeted field. * @return A {@link RangePredicateFieldSetContext} allowing to define field-specific settings * (such as the {@link RangePredicateFieldSetContext#boostedTo(float) boost}), * or simply to continue the definition of the range predicate * ({@link RangePredicateFieldSetContext#from(Object) bounds}, ...). */ default RangePredicateFieldSetContext onField(String absoluteFieldPath) { return onFields( absoluteFieldPath ); }
@Test public void rangeQueryAbove() { SearchQuery<DocumentReference> query = rangeQuery( f -> f.range().onField( FIELD_PATH ).above( Boolean.TRUE ).toPredicate() ); assertHasHitsWithBooleanProperties( query, Boolean.TRUE, Boolean.TRUE ); }
() -> searchTarget.predicate().range().onField( "unknown_field" ) () -> searchTarget.predicate().range().onFields( indexMapping.string1Field.relativeFieldName, "unknown_field" ) () -> searchTarget.predicate().range().onField( indexMapping.string1Field.relativeFieldName ).orField( "unknown_field" ) () -> searchTarget.predicate().range().onField( indexMapping.string1Field.relativeFieldName ).orFields( "unknown_field" )
.predicate( f -> f.range().onField( indexMapping.string1Field.relativeFieldName ) .orField( indexMapping.string2Field.relativeFieldName ) .below( indexMapping.string1Field.document1Value.indexedValue ) .predicate( f -> f.range().onField( indexMapping.string1Field.relativeFieldName ) .orField( indexMapping.string2Field.relativeFieldName ) .above( indexMapping.string2Field.document3Value.indexedValue ) .predicate( f -> f.range().onField( indexMapping.string1Field.relativeFieldName ) .orFields( indexMapping.string2Field.relativeFieldName, indexMapping.string3Field.relativeFieldName ) .below( indexMapping.string1Field.document1Value.indexedValue ) .predicate( f -> f.range().onField( indexMapping.string1Field.relativeFieldName ) .orFields( indexMapping.string2Field.relativeFieldName, indexMapping.string3Field.relativeFieldName ) .from( "d" ).to( "e" ) .predicate( f -> f.range().onField( indexMapping.string1Field.relativeFieldName ) .orFields( indexMapping.string2Field.relativeFieldName, indexMapping.string3Field.relativeFieldName ) .above( indexMapping.string3Field.document3Value.indexedValue ) .predicate( f -> f.range().onFields( indexMapping.string1Field.relativeFieldName, indexMapping.string2Field.relativeFieldName ) .below( indexMapping.string1Field.document1Value.indexedValue ) .toPredicate() .predicate( f -> f.range().onFields( indexMapping.string1Field.relativeFieldName, indexMapping.string2Field.relativeFieldName ) .above( indexMapping.string2Field.document3Value.indexedValue ) .toPredicate()
@Test public void rangeQueryBelow() { SearchQuery<DocumentReference> query = rangeQuery( f -> f.range().onField( FIELD_PATH ).below( Boolean.FALSE ).toPredicate() ); assertHasHitsWithBooleanProperties( query, Boolean.FALSE, Boolean.FALSE ); }
/** * Target the given field in the range predicate. * <p> * Multiple fields may be targeted by the same predicate: * the predicate will match if <em>any</em> targeted field matches. * <p> * When targeting multiple fields, those fields must have compatible types. * See <a href="SearchPredicateFactoryContext.html#commonconcepts-parametertype">there</a> for more information. * * @param absoluteFieldPath The absolute path (from the document root) of the targeted field. * @return A {@link RangePredicateFieldSetContext} allowing to define field-specific settings * (such as the {@link RangePredicateFieldSetContext#boostedTo(float) boost}), * or simply to continue the definition of the range predicate * ({@link RangePredicateFieldSetContext#from(Object) bounds}, ...). */ default RangePredicateFieldSetContext onField(String absoluteFieldPath) { return onFields( absoluteFieldPath ); }
@Test public void rangeQueryFromTo() { SearchQuery<DocumentReference> query = rangeQuery( f -> f.range().onField( FIELD_PATH ).from( Boolean.FALSE ).to( Boolean.FALSE ).toPredicate() ); assertHasHitsWithBooleanProperties( query, Boolean.FALSE, Boolean.FALSE ); }
@Test public void unsupported_field_types() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.unsupportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; SubTest.expectException( "range() predicate with unsupported type on field " + absoluteFieldPath, () -> searchTarget.predicate().range().onField( absoluteFieldPath ) ) .assertThrown() .isInstanceOf( SearchException.class ) .hasMessageContaining( "Range predicates are not supported by" ) .satisfies( FailureReportUtils.hasContext( EventContexts.fromIndexFieldAbsolutePath( absoluteFieldPath ) ) ); } }
() -> searchTarget.predicate().range().onField( absoluteFieldPath ).above( invalidValueToMatch ) () -> searchTarget.predicate().range().onField( absoluteFieldPath ).below( invalidValueToMatch ) () -> searchTarget.predicate().range().onField( absoluteFieldPath ).from( invalidValueToMatch ) () -> searchTarget.predicate().range().onField( absoluteFieldPath ) .from( null ).to( invalidValueToMatch )
SubTest.expectException( "range() predicate with null bounds on field " + fieldPath, () -> searchTarget.predicate().range().onField( fieldPath ).from( null ).to( null ) () -> searchTarget.predicate().range().onField( fieldPath ).above( null ) () -> searchTarget.predicate().range().onField( fieldPath ).below( null )
@Test public void above() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object lowerValueToMatch = fieldModel.predicateLowerBound; SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).above( lowerValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2, DOCUMENT_3 ); } }
@Test public void below() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object upperValueToMatch = fieldModel.predicateUpperBound; SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).below( upperValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1, DOCUMENT_2 ); } }
@Test public void below_withDslConverter() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldWithDslConverterModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object upperValueToMatch = new ValueWrapper<>( fieldModel.predicateUpperBound ); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).below( upperValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1, DOCUMENT_2 ); } }
@Test public void above_withDslConverter() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldWithDslConverterModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object lowerValueToMatch = new ValueWrapper<>( fieldModel.predicateLowerBound ); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).above( lowerValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2, DOCUMENT_3 ); } }
@Test public void above_include_exclude() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object lowerValueToMatch = fieldModel.document2Value.indexedValue; // Default is inclusion SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).above( lowerValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2, DOCUMENT_3 ); // explicit exclusion query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).above( lowerValueToMatch ).excludeLimit().toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_3 ); } }
.asReference() .predicate( f -> f.bool() .must( f.range().onField( "flattenedObject.string" ) .from( MATCHING_STRING ).to( MATCHING_STRING ) .must( f.range().onField( "flattenedObject.integer" ) .from( MATCHING_INTEGER - 1 ).to( MATCHING_INTEGER + 1 ) .must( f.range().onField( "flattenedObject.localDate" ) .from( MATCHING_LOCAL_DATE.minusDays( 1 ) ).to( MATCHING_LOCAL_DATE.plusDays( 1 ) ) .predicate( f -> f.nested().onObjectField( "nestedObject" ) .nest( f.bool() .must( f.range().onField( "nestedObject.string" ) .from( MATCHING_STRING ).to( MATCHING_STRING ) .must( f.range().onField( "nestedObject.integer" ) .from( MATCHING_INTEGER - 1 ).to( MATCHING_INTEGER + 1 ) .must( f.range().onField( "nestedObject.localDate" ) .from( MATCHING_LOCAL_DATE.minusDays( 1 ) ) .to( MATCHING_LOCAL_DATE.plusDays( 1 ) )
@Test public void fromTo() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object lowerValueToMatch = fieldModel.predicateLowerBound; Object upperValueToMatch = fieldModel.predicateUpperBound; SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).from( lowerValueToMatch ).to( upperValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2 ); } }
@Test public void below_include_exclude() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); for ( ByTypeFieldModel<?> fieldModel : indexMapping.supportedFieldModels ) { String absoluteFieldPath = fieldModel.relativeFieldName; Object upperValueToMatch = fieldModel.document2Value.indexedValue; // Default is inclusion SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).below( upperValueToMatch ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1, DOCUMENT_2 ); // explicit exclusion query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( absoluteFieldPath ).below( upperValueToMatch ).excludeLimit().toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); } }
@Test public void rangeFromToSortByFieldQuery() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.range().onField( FIELD_PATH ).from( Boolean.FALSE ).to( Boolean.TRUE ).toPredicate() ) .sort( c -> c.byField( FIELD_PATH ).onMissingValue().sortLast() ) .build(); assertHasHitsWithBooleanProperties( query, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE ); }
.asReference() .predicate( root -> root.bool() .should( c -> c.range().onField( indexMapping.string1Field.relativeFieldName ) .above( indexMapping.string1Field.document3Value.indexedValue ).toPredicate() .should( c -> c.range().onField( indexMapping.string1Field.relativeFieldName ).boostedTo( 42 ) .below( indexMapping.string1Field.document1Value.indexedValue ).toPredicate() .asReference() .predicate( root -> root.bool() .should( c -> c.range().onField( indexMapping.string1Field.relativeFieldName ).boostedTo( 42 ) .above( indexMapping.string1Field.document3Value.indexedValue ).toPredicate() .should( c -> c.range().onField( indexMapping.string1Field.relativeFieldName ) .below( indexMapping.string1Field.document1Value.indexedValue ).toPredicate()