Search and sort other than asc or desc

Hi

I have a photo site where I sort photos on aspect ratios and I have and indexed field with sortable on aspectRatio(derivedFrom width / height), and sorting on panorama or tall photos works fine, i.e aspectRatio desc or asc. But now I want to sort on photos close to a square as well. As such the aspect ratio should be as close to one as possible.

Example:
Photo 1 with aspect ratio: 3 (3000 / 1000)
Photo 2 with aspect ratio: 0.4 (400 / 1000)
Photo 3 with aspect ratio: 1 (500 / 500)

I would then like a list returned as {Photo 3, Photo 2, Photo 1}.

I guess a way to do it could be to make a new field with “@IndexingDependency” and having some calculations on that field, for example absolutte(aspectRatio -1) and then sort on that field. The above would give

Photo 1: 2 abs(3-1)
Photo 2 : 0.6 abs(0.4 -1)
Photo 3: 0.1 abs(1.1-1)

And then sort would give {Photo 3, Photo 2, Photo 1}

Unfortunately this require a fairly complex query since I have to change which field I sort on depending upon the sort {Panorama, tall, square}. I know the algorithm with abs(aspectRatio -1) does not really works since an photo with 200 / 1000 would give 0.8 meaning its close to a square which it is not. But I guess I could come up with something that would make it work but are there another better hibernate way to do it.

Anyone here have any tips or ideas

Hey,

Thanks for reaching out. Depending on the particular backend you are using, you might be able to leverage some backed-specific features. For example, with an Elasticsearch backend, you may try to use something like a script-based sorting. But this would just move the “query complexity” as you named it into the script and will slow things down.
Since you have three options (panorama, tall, square), I can’t think of a way to use just asc/desc sort order to achieve what you are asking.
What I can suggest for making the query construction cleaner is to have dedicated fields in the index and pass the sort option (panorama, tall, square) as an enum and store the field/order in the enum. Something along the next lines:

enum PhotoTypeSort {
	SQUARE( "squareSort", SortOrder.DESC ),
	TALL( "wideSort", SortOrder.ASC ),
	PANORAMA( "wideSort", SortOrder.DESC ); // using the same field for wide photos, but can also have a dedicated field and then use same DESC order for all cases. 

	final String field;
	final SortOrder order;

	PhotoTypeSort(String field, SortOrder order) {
		this.field = field;
		this.order = order;
	}
}

PhotoTypeSort sort = ... ; // get this from the search request

searchSession.search( Photo.class )
		.where( /* any predicates you need or a match all */ )
		.sort( f -> f.field( sort.field ).order( sort.order ) ) 
		.fetchHits( 20 );

Also, another idea – depending on your needs, maybe you’d be able to get away without sorting but instead have a derived multivalue field with “classifiers”. Instead of sorting the results at the query time, determine to which categories (panorama, tall, square) the photo is likely to belong and store those at an index time. Then during the search, have a filter for a type you need. Most photos would have one category, except maybe those that are close to the criteria of being wide/tall but still might be considered square ones.

1 Like

Thanks for good ideas. The classifiers idea sounds nice but then all panorama would be similar, i.e 2000 / 200 is more panorama than 2000 / 400. But I like the idea of having the PhotoTypeSort enum with the field, since then it is clear how the sorting is done. I will try that one.