Populate Projection Fields Dynamically - Hibernate Search 7.2.1

Hello, We are migrating from hibernate 5 to 6 with lucene backend. Made few changes and able to get results without projections. When it comes to projections, the existing application populates the fields dynamically and sets it to the full text query. But in hibernate 6, the projection fields seem to be predefined as per the documents i.e., defined as composite fields or using projection constructors taking in predefined parameters. The below query returns the results correctly when I provide these fields manually. But in our case, the fields come up dynamically through a string array. Is there a way to populate the projection fields each time from the String array?

session.search(XxxRequest.class)
                            .select(f -> f.composite()
                                    .from( f.field("pk", String.class),
                                            f.field("approvedTime", LocalDateTime.class),
                                            f.field("claimedTime", LocalDateTime.class),
                                            f.field("creationTime", LocalDateTime.class),
                                            f.field("franchise", String.class)).asList())
                            .where(f -> f.match().field("status").matching("claimed"))
                            .toQuery();

Hey,

Thanks for reaching out. What you could try doing here is:

// Create a scope for your entity/entities you want to search 
// so that we can get access to the projection factory:
SearchScope<XxxRequest> scope = searchSession.scope( XxxRequest.class );

// get the factory
var projectionFactory = scope.projection();
List<SearchProjection<?>> projections = new ArrayList<>();

// create the projections you need based on the fields you've received.
// if you need other type of projections than fields you have to decide 
// that based on field name or whatever the rules you want to apply
for ( String field : fieldsToReturn ) {
	projections.add( projectionFactory.field( field ).toProjection() );
}

// either use the scope, or you can pass an entity 
List<List<?>> hits = searchSession.search( scope )
		// pass the array of projections to select:
		.select( projections.toArray( SearchProjection[]::new ) )
		// add any predicates you want:
		.where( f -> f.matchAll() )
		.fetchHits( 20 );

If you need a composite projection, there’s a version of it that accepts an array of search projections as well.

Alternatively… if the number of fields is constant and it’s just the field names that change, you may also try using the .withParameters(...) projection: Hibernate Search 7.2.1.Final: Reference Documentation where you’d pass field names as parameters.

Great!!Thanks for your immediate response. It worked.