Skip to content

Fix handling of array-of-strings parameters for @Query-annotated queries #2182

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

Merged
merged 2 commits into from
Jun 27, 2022

Conversation

diamondT
Copy link
Contributor

@diamondT diamondT commented Jun 5, 2022

As described in the linked ticket, elasticsearch queries do not play along with array (collection) parameters. This appears to be happening for reactive repositories only.

Proposing to handle collections explicitly in ConvertingParameterAccessor and then the rest should fall into place in StringQueryUtil#convert.
Also proposing to amend the unit tests for reactive repositories (ReactiveElasticsearchStringQueryUnitTests) to use the ConvertingParameterAccessor as well.

Let me know what you think.

Thanks,

Closes #2135

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 5, 2022
@sothawo
Copy link
Collaborator

sothawo commented Jun 22, 2022

Sorry for the late reaction; I had two weeks vacation, and now I'm sick; but I'll have a look this week

@sothawo
Copy link
Collaborator

sothawo commented Jun 23, 2022

Having a closer look at this, I have to admit that it is a kind of mess - not your PR, thanks for that, but the existing code. Both the imperative and reactive part were written by different people before my time, I think this needs some consolidation.

I was just playing around a little in the ReactiveElasticsearchStringQueryUnitTests class and added these two test functions (wanted to check Integer arrays)

@Test // #THIS-SHOULD_BE_THE ACTUAL _ISSUE_NUMBER
@DisplayName("should handle array-of-strings parameters correctly")
void shouldHandleArrayOfStringsParametersCorrectly() throws Exception {
	List<String> otherNames = List.of("Wesley", "Emmett");
	org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByOtherNames", otherNames);
	assertThat(query).isInstanceOf(StringQuery.class);
	assertThat(((StringQuery) query).getSource())
		.isEqualTo("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : [\"Wesley\",\"Emmett\"] } } } }");
}

@Test // #THIS-SHOULD_BE_THE ACTUAL _ISSUE_NUMBER
@DisplayName("should handle array-of-Integers parameters correctly")
void shouldHandleArrayOfIntegerParametersCorrectly() throws Exception {
	List<Integer> ages = List.of(42, 57);
	org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByAges", ages);
	assertThat(query).isInstanceOf(StringQuery.class);
	assertThat(((StringQuery) query).getSource())
		.isEqualTo("{ 'bool' : { 'must' : { 'terms' : { 'ages' : [42,57] } } } }");
}

together with these repository functions:

@Query("{ 'bool' : { 'must' : { 'terms' : { 'otherNames' : ?0 } } } }")
Flux<Person> findByOtherNames(List<String> otherNames);

@Query("{ 'bool' : { 'must' : { 'terms' : { 'ages' : ?0 } } } }")
Flux<Person> findByAges(List<Integer> ages);

and a modified createQuery (taking your change and using ReactiveElasticsearchParametersParameterAccessor)

private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, Object... args)
	throws NoSuchMethodException {

	Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass)
		.map(clazz -> Collection.class.isAssignableFrom(clazz) ? List.class : clazz).toArray(Class[]::new);
	ReactiveElasticsearchQueryMethod queryMethod = getQueryMethod(methodName, argTypes);
	ReactiveElasticsearchStringQuery elasticsearchStringQuery = queryForMethod(queryMethod);

	return elasticsearchStringQuery
		.createQuery(new ReactiveElasticsearchParametersParameterAccessor(queryMethod, args));
}

I am on purpose not using the ConvertingParameterAccessor here, because the conversion of parameters (and in the case of a collection of the single collection elements) is done in org.springframework.data.elasticsearch.repository.support.StringQueryUtil#convert .

This tests then pass. I have not tried it in an integration test.

I think if we'd change the same way to build the query in ReactiveElasticsearchStringQuery this would be closer to the way it is done in the imperative part. Basically that would mean to just skip wrapping the parameterAccessor argument in org.springframework.data.elasticsearch.repository.query.AbstractReactiveElasticsearchRepositoryQuery#execute(org.springframework.data.elasticsearch.repository.query.ElasticsearchParameterAccessor) in a ConvertingParameterAccessor. We could drop the ConvertingParameterAccessor then altogether, it's not used anywhere else.

What do you think?

@diamondT
Copy link
Contributor Author

thanks for taking the time to look into this.
if we can drop ConvertingParameterAccessor then yes i agree what you are proposing is cleaner. i assumed that the wrapper was there for a reason but - as you said - it might be simply because different people wrote different parts.

if that's ok, i can continue with dropping the accessor (should i just delete it?), copy your array-of-integers unit test and introduce an integration test for the same (already done for array-of-strings).

thanks,

@sothawo
Copy link
Collaborator

sothawo commented Jun 24, 2022

dropping the accessor (should i just delete it?),

yes, it has just this one use. And code that is not used should be removed.

- fix issue number in previous unit test
- introduce unit test for array of integers
- introduce integration test for array of integers
@diamondT
Copy link
Contributor Author

done. also fixed a typo, had the wrong ticket number...

@sothawo sothawo merged commit 259c43a into spring-projects:main Jun 27, 2022
sothawo pushed a commit that referenced this pull request Jul 12, 2022
…ies.

Original Pull Request  #2182
Closes #2135

(cherry picked from commit 259c43a)
sothawo pushed a commit that referenced this pull request Jul 12, 2022
…ies.

Original Pull Request  #2182
Closes #2135

(cherry picked from commit 259c43a)
(cherry picked from commit aa4aeca)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@Query annotation fails to parse Collection parameters in ReactiveRepository
3 participants