Skip to content

Spring Data Repository not taking into account @Field(name) annotation when generating queries for Object Fields #1752

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

Closed
Mynameisbt opened this issue Apr 1, 2021 · 7 comments
Labels
status: feedback-provided Feedback has been provided

Comments

@Mynameisbt
Copy link

Mynameisbt commented Apr 1, 2021

I am having an issue when trying to do a search with a Spring Data Elasticsearch 4 repository when using a Object Field Type. Below is a simple example that is replicating the issue I am having in my application. With Spring Data Elasticsearch 3 the query generated by the repository would use the @Field(name) value but it no longer does with Spring Data Elasticsearch 4.

The query that it is generating for the Authors.FirstName field repository method according to the logs is:

Request body: {"from":0,"size":10000,"query":{"bool":{"must":[{"query_string":{"query":"John","fields":["authors.firstName^1.0"],"type":"best_fields","default_operator":"and","max_determinized_states":10000,"enable_position_increments":true,"fuzziness":"AUTO","fuzzy_prefix_length":0,"fuzzy_max_expansions":50,"phrase_slop":0,"escape":false,"auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":1.0}}],"adjust_pure_negative":true,"boost":1.0}},"version":true}

I would have expected the fields query to be:

["Authors.FirstName^1.0"]

based on the @Field annotation. That is what Spring Data Elasticsearch 3 would generate

Is there something I am missing in my configuration for the query to use the @Field(name) value in Spring Data Elasticsearch 4?

I have a github test setup that reproduces the problem. I just run a Elasticsearch docker container prior to executing the test.

https://github.com/Mynameisbt/nestedobjectquerytest/blob/master/src/test/java/com/mynameisbt/nestedobjectquerytest/NestedobjectquerytestApplicationTests.java

If I remove the custom names for authors and first name then the documents get returned.

@Document(indexName = "blog", type = "article")
public class Article {
    @Id
    private String id;
    @MultiField(mainField = @Field(type = Text, fielddata = true), otherFields = {@InnerField(suffix = "verbatim", type = Keyword)})
    private String title;

    @Field(type = FieldType.Object, name = "Authors")
    private List<Author> authors;

    @Field(type = Keyword)
    private String[] tags;

    public Article() {
    }

    public Article(String title) {
        this.title = title;
    }
}

Subclass

public class Author {
    @Field("FirstName")
    private String firstName;
    @Field("LastName")
    private String lastName;

Repository

public interface ArticleRepository extends ElasticsearchRepository<Article, String> {

    Page<Article> findByAuthorsFirstName(String name, Pageable pageable);
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 1, 2021
@Mynameisbt Mynameisbt changed the title Repository Query not taking into account @Field(name) annotation when generating queries for Objects Repository Query not taking into account @Field(name) annotation when generating queries for Object Fields Apr 1, 2021
@Mynameisbt Mynameisbt changed the title Repository Query not taking into account @Field(name) annotation when generating queries for Object Fields Spring Data Repository not taking into account @Field(name) annotation when generating queries for Object Fields Apr 1, 2021
@sothawo
Copy link
Collaborator

sothawo commented Apr 1, 2021

The problem is that the @Field annotations of the properties of Author do not have a type attribute set, meaning the filed type for Elasticsearch is autodetected and therefore no mapping is written - even if a namewas specified. You will need to change that to:

public class Author {
    @Field(value = "FirstName", type = FieldType.Text)
    private String firstName;
    @Field(value = "LastName", type = FieldType.Text)
    private String lastName;
}

I will add a description of this behaviour to the documentation.

But even with this change, the test will fail, because currently the CriteriaQuery - and the repository implementation creates one under the hood - does not support queries on nested objects see my answer on this SO question where this came up as well.

I will later create a bug issue for this, as this should definitely be possible.

@sothawo sothawo removed the status: waiting-for-triage An issue we've not yet triaged label Apr 1, 2021
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 1, 2021
@sothawo
Copy link
Collaborator

sothawo commented Apr 3, 2021

Not having the type defined in the @Field annotations is no problem. The field won't be written to the index mapping on index creation, but later will be autodetected as a text field with the desired name (FirstName, LastName).

But the problem really is the nested query. I have implemented a fix with #1753, this will be available from the next version on - which will be Spring Data Elasticsearch 4.2.0 GA.

Your demo application successfully runs with this version, what must be changed is:

@Field(type = FieldType.Nested, name = "Authors")
private List<Author> authors;

The type must be changed to FieldType.Nested as we need a nested query in this case.

@sothawo sothawo added the status: waiting-for-feedback We need additional information before we can continue label Apr 5, 2021
@Mynameisbt
Copy link
Author

Shouldn't it also pass even if the FieldType is FieldType.Object?

I know in the Author example it makes sense to use FieldType.Nested and a nested query for names to maintain the independence of each object vs FieldType.Object where the objects are flatted. https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html

But in my example even with a FieldType.Object query where the object arrays are flattened I would expect it to return the same 4 documents since the query is just on the FirstName field which is on all 4 documents.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 6, 2021
@sothawo
Copy link
Collaborator

sothawo commented Apr 6, 2021

I added another fix #1761 so now a nested query is only used when the FieldType.Nested is defined, otherwise a normal query is used.
Your demo code runs now with no change - at least no change relevant to the problem, you will need to remove the type attribute from the @Document annotation.

@sothawo sothawo added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Apr 6, 2021
@Mynameisbt
Copy link
Author

Thanks for making the fixes. Will these fixes also be added to 4.0.9 and 4.1.8 releases or will I need to update to version 4.2?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 6, 2021
@sothawo
Copy link
Collaborator

sothawo commented Apr 8, 2021

I will check this evening if this can be backported

@sothawo
Copy link
Collaborator

sothawo commented Apr 8, 2021

Alas these changes cannot be easily backported to the 4.1 and 4.0 branches, because we had major rewritings in the MappingElasticsearchConverter class last february, and that's one of the classes affected by the changes for this nested names fixes.

@sothawo sothawo closed this as completed Apr 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: feedback-provided Feedback has been provided
Projects
None yet
Development

No branches or pull requests

3 participants