-
Notifications
You must be signed in to change notification settings - Fork 1.3k
add routing support for repository operations #1906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
|
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed. |
ok, I found the method |
I checked the code and found that Spring Data Elasticsearch supports the routing when creating, updating and deleting entities. But not in search requests. This should have been done in #1218 but it was missed there. Thanks for finding this. This not only is an error in the reactive code, but in the imperative as well. As for the |
I just started to get deeper into this and just am wondering how the The So how should this be used in the repository context? Can you provide a concrete example of how this should work? |
The way I see it, when you need to for example findById (which accepts only ID for entity) and routing is something required on elastic mapping or mandatory by your business logic, the only way to pass routing value for whatever property you use for routing is to use something like
with following implementation:
} This for now works for my scenario, but if it could be done automatically for findBy...WithRouting methods without need for special interface and impl, would be great. |
Ok, I see the point. The bad news: It's not possible just by using a method name like The good news: it's not as complicated as in the code you wrote. You need to implement custom repository fragments, let me show this in an example. In my test application a have a We start with an interface definition for a routing repository: RoutingRepositorypublic interface RoutingRepository<T, ID> {
Mono<T> findByIdWithRouting(ID id, String routing);
} This is just a plain interface defining the desired methods, not extending anything, no spring or spring data stuff The next is an abstract implementation of this interface: AbstractRoutingRepositorypublic abstract class AbstractRoutingRepository<T, ID> implements RoutingRepository<T, ID> {
private final ReactiveElasticsearchOperations operations;
private final Class<T> clazz;
protected AbstractRoutingRepository(ReactiveElasticsearchOperations operations, Class<T> clazz) {
this.operations = operations;
this.clazz = clazz;
}
@Override
public Mono<T> findByIdWithRouting(ID id, String routing) {
var stringId = operations.getElasticsearchConverter().convertId(id);
return operations.withRouting(RoutingResolver.just(routing))
.get(stringId, clazz);
}
} Classes extending will provide an In the implementation of the So this is what you need to implement: call the methods of the The next step is to define a concrete interface: PersonCustomRepositorypublic interface PersonCustomRepository extends RoutingRepository<Person, String> {
} Just a typed version of the interface. The repository we use in our program will extend from this and Spring Data PersonCustomRepositoryImplpublic class PersonCustomRepositoryImpl extends AbstractRoutingRepository<Person, String> implements PersonCustomRepository {
public PersonCustomRepositoryImpl(ReactiveElasticsearchOperations operations) {
super(operations, Person.class);
}
} This implementation will be instantiated by Spring Data Elasticsearch and will have the And now the final repository interface: PersonRepositorypublic interface PersonRepository extends ReactiveElasticsearchRepository<Person, Long>,
PersonCustomRepository {
} This is a normal Spring Data Elasticsearch repository but also extending our custom interface. You'll have this So you will have to do the implementation by yourself, but you can use the methods of the Hope that helps. |
Your suggested code would require 1 class + 1 interface PER business entity, instead of only 1 interface per entity. What I was trying to anchieve (but maybe not as clean code since I'm not familiar with internals of spring-data or spring-data/elasticsearch) is to not have the need for passing a Class clazz on the implementation, since it seemed to me that from inside SimpleReactiveElasticsearchRepository you could get which entity class is this repository created for from the Maybe possible to merge both options, and have cleaner code (like yours) on the implementation but without the need for passing Class clazz , thus avoiding the need for 1 additional impl class for each entity?? |
...actually 1 class + 2 interfaces PER business entity... |
Yes, what I showed was customization of single repositories. But you can as well change the base implementation merging your approach with my custom implementation (I only show one of the methods): RoutingAwareReactiveElasticsearchRepository@NoRepositoryBean
public interface RoutingAwareReactiveElasticsearchRepository<T, ID> extends ReactiveElasticsearchRepository<T, ID> {
Mono<T> findByIdWithRouting(ID id, String routing);
} Please mark the RoutingAwareReactiveElasticsearchRepositoryImplpublic class RoutingAwareReactiveElasticsearchRepositoryImpl<T, ID> extends SimpleReactiveElasticsearchRepository<T, ID>
implements RoutingAwareReactiveElasticsearchRepository<T, ID> {
private final ElasticsearchEntityInformation<T, ID> entityInformation;
private final ReactiveElasticsearchOperations operations;
private final ReactiveIndexOperations indexOperations;
public RoutingAwareReactiveElasticsearchRepositoryImpl(ElasticsearchEntityInformation<T, ID> entityInformation, ReactiveElasticsearchOperations operations) {
super(entityInformation, operations);
this.entityInformation = entityInformation;
this.operations = operations;
this.indexOperations = operations.indexOps(entityInformation.getJavaType());
}
@Override
public Mono<T> findByIdWithRouting(ID id, String routing) {
var stringId = operations.getElasticsearchConverter().convertId(id);
return operations.withRouting(RoutingResolver.just(routing)).get(stringId, entityInformation.getJavaType());
}
} no need to copy all that callback stuff, use PersonRepositorypublic interface PersonRepository extends RoutingAwareReactiveElasticsearchRepository<Person, Long> {
} You need to adapt the interface your repositories extend Configuration@SpringBootApplication(exclude = ElasticsearchDataAutoConfiguration.class)
@EnableReactiveElasticsearchRepositories(repositoryBaseClass = RoutingAwareReactiveElasticsearchRepositoryImpl.class)
public class SpringdataElasticTestApplication {
//...
} Set the repository base class in the And for the other methods just build a |
That's perfect, thank you. |
For the And even more problematic: If you have a property defined like this: @Field(name="foo-bar", type = FieldType.text)
private String fooBar where the property name and the field name in Elasticsearch differ, the caller of the method would need to remember this when passing in these names in the parameter map's keys. For date fields the caller would need to manually convert the date property to a String value in the format that was defined on the property. These conversions are normally done transparently for the user. So the user would anyway need a custom implementation. |
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed. |
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue. |
@sothawo Sorry to open this again but is there a way around it, I am using |
This issue was about routing support in repositories, you are using operations, that's something different. Please create a new issue and provide a compilable, runnable example that show your issue. |
It seems that when using ReactiveElasticsearchRepository, findBy(...) methods don't use the @routing annotation on the entity when building the SearchRequest.
For performance sensitive applications, this means we can't use repositories and are stuck with manually building query and using ReactiveElasticsearchTemplate.
Would be nice to have support for routing on the repository level.
Any ideas going around about this?
I can try to implement it if there aren't any arguments against it...
The text was updated successfully, but these errors were encountered: