Search by just one child object

I’m trying to search an entity by the field of only one child entity but cannot figure it out. In this situation:

@Indexed
class Author {
	@IndexedEmbedded
	@OneToMany(mappedBy = "bookId")
	@OrderBy("created DESC") // sort latest first
	List<Book> books;
}

class Book {
	@Field
	private name: String;
}

How would I search for a Person by the name of their latest book?
I don’t see how to access just one of an indexed list of child objects, and strategies of having a @Transient that returns getBooks().get(0) aren’t working for me either.

What you’re trying to do, with your current mapping, would require some sort of aggregation during Search, which is not implemented in Hibernate Search (and I’m not sure it’s possible with Elasticsearch either, to be honest).

What you can do, however, is change your mapping to index the latest book of each author explicitly:

@Index
class Author {
	@OneToMany(mappedBy = "bookId")
	@OrderBy("created DESC") // sort latest first
	List<Book> books;

	@javax.persistence.Transient
	@IndexedEmbedded
	public Book getLatestBook() {
		return books == null || books.isEmpty() ? null : books.get(0);
	}
}

class Book {
	@Field
	private name: String;
}

Then you will have a field named “latestBook.name” in the author index that you can query as you want.

Note that indexing a transient method has some implications performance-wise: it disables an optimization that would have made sure the author is reindexed only when changes to the author affect its indexed form. With a transient method, Hibernate Search can’t know what change would affect the result of that method, so it has to give up on optimizing.
Everything should work fine apart from that.

One last thing: if your Book entities are mutable, you might want to add a @ContainedIn annotation on the author property of the Book entity. Otherwise, the author may not get reindexed when the title of a book is changed. See the documentation for details: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-mapping-associated

Hum, just saw you said @Transient doesn’t work for you… I guess my answer above is useless, then. What doesn’t work exactly?

That is indeed the exact approach I tried, but I had done something foolish with the name of the method and then tried to fix it with field names etc. Seeing your example meant I could fix it so it worked.

Thanks very much!

No problem, glad it helped :slight_smile: