/** * Add a <a href="#must">"must" clause</a> based on an almost-built {@link SearchPredicate}. * * @param terminalContext The terminal context allowing to retrieve a {@link SearchPredicate}. * @return {@code this}, for method chaining. */ default BooleanJunctionPredicateContext must(SearchPredicateTerminalContext terminalContext) { return must( terminalContext.toPredicate() ); }
@Test public void must_mustNot() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .mustNot( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .toPredicate() ) .build(); assertThat( query ).hasNoHits(); query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .mustNot( f.match().onField( "field1" ).matching( FIELD1_VALUE2 ) ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); }
/** * Add a <a href="#must">"must" clause</a> based on an almost-built {@link SearchPredicate}. * * @param terminalContext The terminal context allowing to retrieve a {@link SearchPredicate}. * @return {@code this}, for method chaining. */ default BooleanJunctionPredicateContext must(SearchPredicateTerminalContext terminalContext) { return must( terminalContext.toPredicate() ); }
@Test public void nested() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.bool() .should( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .should( f.match().onField( "field1" ).matching( FIELD1_VALUE3 ) ) ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1, DOCUMENT_3 ); query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.bool() .should( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .should( f.match().onField( "field1" ).matching( FIELD1_VALUE3 ) ) ) .mustNot( f.match().onField( "field1" ).matching( FIELD1_VALUE3 ) ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); }
.predicate( f -> f.bool() .must( f.nested().onObjectField( "nestedObject.nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.nestedObject.field1" ) .matching( MATCHING_SECOND_LEVEL_CONDITION1_FIELD1 ) .must( f.match() .onField( "nestedObject.nestedObject.field2" ) .matching( MATCHING_SECOND_LEVEL_CONDITION1_FIELD2 ) .must( f.nested().onObjectField( "nestedObject.nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.nestedObject.field1" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD1 ) .must( f.match() .onField( "nestedObject.nestedObject.field2" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD2 )
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "string_analyzed" ).matching( "text" ) ) .filter( f.match().onField( "integer" ).matching( 1 ) ) .toPredicate() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "string_analyzed" ).matching( "text" ) ) .mustNot( f.match().onField( "integer" ).matching( 2 ) ) .toPredicate()
.nest( f.bool() .must( f.nested().onObjectField( "nestedObject.nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.nestedObject.field1" ) .matching( MATCHING_SECOND_LEVEL_CONDITION1_FIELD1 ) .must( f.match() .onField( "nestedObject.nestedObject.field2" ) .matching( MATCHING_SECOND_LEVEL_CONDITION1_FIELD2 ) .must( f.nested().onObjectField( "nestedObject.nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.nestedObject.field1" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD1 ) .must( f.match() .onField( "nestedObject.nestedObject.field2" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD2 )
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "flattenedObject.string" ).matching( MATCHING_STRING ) ) .must( f.match().onField( "flattenedObject.string_analyzed" ).matching( MATCHING_STRING_ANALYZED ) ) .must( f.match().onField( "flattenedObject.integer" ).matching( MATCHING_INTEGER ) ) .must( f.match().onField( "flattenedObject.localDate" ).matching( MATCHING_LOCAL_DATE ) ) .toPredicate() .predicate( f -> f.nested().onObjectField( "nestedObject" ) .nest( f.bool() .must( f.match().onField( "nestedObject.string" ).matching( MATCHING_STRING ) ) .must( f.match().onField( "nestedObject.string_analyzed" ).matching( MATCHING_STRING_ANALYZED ) ) .must( f.match().onField( "nestedObject.integer" ).matching( MATCHING_INTEGER ) ) .must( f.match().onField( "nestedObject.localDate" ).matching( MATCHING_LOCAL_DATE ) )
.predicate( f -> f.nested().onObjectField( "nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.string" ) .matching( MATCHING_STRING ) .must( f.nested().onObjectField( "nestedObject.nestedObject" ) .nest( f.bool() .must( f.match() .onField( "nestedObject.nestedObject.field1" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD1 ) .must( f.match() .onField( "nestedObject.nestedObject.field2" ) .matching( MATCHING_SECOND_LEVEL_CONDITION2_FIELD2 )
@Override public List<Book> searchByMedium(String terms, BookMedium medium, int offset, int limit) { FullTextQuery<Book> query = entityManager.search( Book.class ).query() .asEntity() .predicate( f -> f.bool( b -> { if ( terms != null && !terms.isEmpty() ) { b.must( f.match() .onField( "title" ).boostedTo( 2.0f ) .orField( "summary" ) .matching( terms ) ); } b.must( f.nested().onObjectField( "copies" ) .nest( f.match().onField( "copies.medium" ).matching( medium ) ) ); } ) ) .sort( b -> b.byField( "title_sort" ) ) .build(); query.setFirstResult( offset ); query.setMaxResults( limit ); return query.getResultList(); }
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .toPredicate() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .must( f.match().onField( "field2" ).matching( FIELD2_VALUE2 ) ) .toPredicate() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .must( f.match().onField( "field2" ).matching( FIELD2_VALUE1 ) ) .toPredicate()
.predicate( f -> f.bool().must( cachingContributor ).toPredicate() ) .build();
.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 must_function() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f2 -> f2.match().onField( "field1" ).matching( FIELD1_VALUE1 ).toPredicate() ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); }
@Test public void must_separatePredicateObject() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchPredicate predicate = searchTarget.predicate().match().onField( "field1" ).matching( FIELD1_VALUE1 ).toPredicate(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool().must( predicate ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); }
@Override public List<Book> searchByMedium(String terms, BookMedium medium, int offset, int limit) { FullTextSearchTarget<Book> target = entityManager.search( Book.class ); BooleanJunctionPredicateContext booleanBuilder = target.predicate().bool(); if ( terms != null && !terms.isEmpty() ) { booleanBuilder.must( target.predicate().match() .onField( "title" ).boostedTo( 2.0f ) .orField( "summary" ) .matching( terms ) ); } booleanBuilder.must( target.predicate().nested().onObjectField( "copies" ) .nest( target.predicate().match().onField( "copies.medium" ).matching( medium ) ) ); FullTextQuery<Book> query = entityManager.search( Book.class ).query() .asEntity() .predicate( booleanBuilder.toPredicate() ) .sort( target.sort().byField( "title_sort" ).toSort() ) .build(); query.setFirstResult( offset ); query.setMaxResults( limit ); return query.getResultList(); }
@Test public void must_should() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); // A boolean predicate with must + should clauses: // documents should match regardless of whether should clauses match. // Non-matching "should" clauses SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE1 ) ) .should( f.match().onField( "field2" ).matching( FIELD2_VALUE2 ) ) .should( f.match().onField( "field3" ).matching( FIELD3_VALUE3 ) ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1 ); // One matching and one non-matching "should" clause query = searchTarget.query() .asReference() .predicate( f -> f.bool() .must( f.match().onField( "field1" ).matching( FIELD1_VALUE2 ) ) .should( f.match().onField( "field2" ).matching( FIELD2_VALUE1 ) ) .should( f.match().onField( "field3" ).matching( FIELD3_VALUE3 ) ) .toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2 ); }
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "field4" ).matching( FIELD4_VALUE1AND2 ) ) .minimumShouldMatchNumber( -1 ) .should( f.match().onField( "field2" ).matching( FIELD2_VALUE2 ) )
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "field4" ).matching( FIELD4_VALUE1AND2 ) ) .minimumShouldMatchPercent( -50 ) .should( f.match().onField( "field2" ).matching( FIELD2_VALUE2 ) )
.asReference() .predicate( f -> f.bool() .must( f.match().onField( "field4" ).matching( FIELD4_VALUE1AND2 ) ) .minimumShouldMatchPercent( 50 ) .should( f.match().onField( "field2" ).matching( FIELD2_VALUE2 ) )