quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.57k stars 2.63k forks source link

Hibernate Search with Panache #42863

Open yrodiere opened 2 weeks ago

yrodiere commented 2 weeks ago

Description

Creating this for tracking, to assess demand and collect suggestions.

We currently have a Panache extensions for Hibernate ORM, one for Hibernate Reactive, and one for MongoDB.

We don't have one for Hibernate Search, despite Hibernate Search exposing very advanced and useful search features. We should aim to change that.

The idea would be to allow an extra interface on Panache repositories, exposing a search() method which can then be used this way:

List<Book> hits = Book.search()
                    .where( f -> f.match().field( "title" ).matching( "robot" ) )
                    .find()
                    .page( Page.of( 0, 20 ) )
                    .list();

With plenty of variants, e.g. to project on an entity reference only:

List<EntityReference> hits = Book.search()
                    .select( f -> f.entityReference() )
                    .where( f -> f.match().field( "title" ).matching( "robot" ) )
                    .find()
                    .page( Page.of( 0, 20 ) )
                    .list();

For the active record pattern, we'll probably need a dedicated superclass, e.g. PanacheSearchableEntityBase.

Implementation ideas

See https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/case.20-insenstive-query-panache/near/207954740 for the whole discussion

In particular:

As to how we'd expose it, I'd say:

  • create a separate extension hibernate-search-orm-elasticsearch-panache
  • add an SPI in hibernate-orm-panache to allow other extensions to register extended PanacheEntityBase/PanacheRepository types
  • create a PanacheSearchableEntityBase and register it to the hibernate-orm-panache extension so that it triggers the correct bytecode generation
  • create a PanacheSearchableRepository interface and register it in a similar way
  • Later, we might need to support multiple extensions in the same entity class, for example to support both Envers and Search. For these (admittedly rare) cases, I'd be inclined to expose a method like this in PanacheEntityBase: static <T> T extension(Class<T> extension). A user would select one "main" base class, e.g. PanacheEnversEntityBase, and to access other extensions they would write MyEntity.extension(PanacheSearch.class).search().

Note there is a (very early) prototype already available here: https://github.com/yrodiere/hibernate-search/tree/panache

quarkus-bot[bot] commented 2 weeks ago

You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip

This message is automatically generated by a bot.

quarkus-bot[bot] commented 2 weeks ago

/cc @FroMage (panache), @gsmet (hibernate-search), @loicmathieu (panache), @marko-bekhta (hibernate-search)

FroMage commented 2 weeks ago

This looks great.

I am thinking this would be much easier to achieve with the new Panache 2 style, where you'd be able to write:

@Entity
public class Book extends PanacheManagedEntity implements SearchableEntity {
}

Which would allow us to compose things easier than making multiple entity superclasses. I would have loved to get rid of the "class that holds the ID" (aka PanacheEntity ATM, but also PanacheManagedEntity and PanacheStatelessEntity in Panache 2) and replace it with an interface, but did not find any trick to make it work.

loicmathieu commented 2 weeks ago

An integration with Hibernate search is definitely a good idea. Is there an implementation for MongoDB? As far as I know, we don't have an integration for it yet.

It makes me think that I have a very old prototype for a Hibernate Search with Panache using the POJO standalone mapper for non-ORM users. At the time I created it the mapper was experimental so I didn't go further.

It also makes me think that, for MongoDB, we want to have a bridge between MongoDB with Panache and Morphia.

So yes, having an easy way to offer multiple functionalities inside Panache by just adding an extension and inheriting from an interface would be great.

yrodiere commented 2 weeks ago

It makes me think that I have a very old prototype for a Hibernate Search with Panache using the POJO standalone mapper for non-ORM users. At the time I created it the mapper was experimental so I didn't go further.

I already implemented that, without Panache -- though I couldn't salvage much from your prototype which was based on Panache... sorry. https://quarkus.io/version/main/guides/hibernate-search-standalone-elasticsearch

Is there an implementation for MongoDB? As far as I know, we don't have an integration for it yet.

There is not, but that could be considered.

If you mean "something that indexes MongoDB entities into Elasticsearch", that's theoretically doable with the Standalone mapper (possibly in a different extension), provided the MongoDB client exposes the right callbacks to send events to Hibernate Search -- but we'd have to check if it really makes sense, as I've seen many native full-text features in MongoDB last time I checked their documentation.

If you mean "something that uses MongoDB as a backend in Hibernate Search instead of Elasticsearch", I suspect that will mean many missing features (exceptions thrown all over the place), so I personally would not do that.

loicmathieu commented 2 weeks ago

I already implemented that, without Panache -- though I couldn't salvage much from your prototype which was based on Panache... sorry. https://quarkus.io/version/main/guides/hibernate-search-standalone-elasticsearch

Great! This can be a good foundation for a new Panache "flavor" if we want, by offering entity or repository pattern on top of that to provide common DAO methods.

I've seen many native full-text features in MongoDB last time I checked their documentation.

Yes, I agree, but relational databases also propose more and more full-text features ;). Anyway this would be a lot of work so I'm not sure it would worth it.

If you mean "something that uses MongoDB as a backend in Hibernate Search instead of Elasticsearch",

Oh no, not that!