Search code examples
javaelasticsearchspring-datafuzzy-searchspring-data-elasticsearch

How to query Elastic with Spring-data-elastic


I am new to Elastic and spring-data-elastic. I am been searching here and other areas of the web, but so far have been unable to find the answer to my question. I am hoping SO might be able to help.

I am indexing some records from my Users table (firstName, lastName) and I am looking to be able to allow advanced searching. So for example if I have the name 'Frances' and I enter 'Frank' then the system is smart enough to return the record. Same for 'Robinson' and 'Robinsen', etc.

I've setup my POJO to be the following:

Public Users {
    @Field(fieldType = FieldType.String)
    private String firstName;

    @Field(fieldType = FieldType.String)
    private String lastName

    // mutators
    ...

 }

Currently I am using a spring-data-elastic ElasticRepository to do my searching, which I believe will probably have to change if I am going to allow for advanced searching. One option would be to use the EntityManager or Template directly in the UserService, however I'm not sure how to go about doing that just yet.

As I've described the problem, is this an indexing issue or a searching issue or possibly both? I'm not looking for anyone to do the work, just to point me in the right direction.

Thanks!


Solution

  • First, there is not support for automatic fuzzy query generation, as far as the documentation tells

    So we'll have to use custom repository methods additions.

    Say your base repository is

    @Repository
    public interface UserRepository extends CrudRepository<UserEntity, Long>
    

    You'll have to create a Custom repository interface to add you custom method (this is all standard Spring data, nothing particular)

    public interface UserRepositoryCustom {
        public List<User> findFuzzyByLastNameAndFirstName(String firstName, String lastName);
    }
    

    And make your historic repo implement this interface, that is :

    @Repository
    public interface UserRepository extends CrudRepository<UserEntity, Long>, UserRepositoryCustom
    

    Now, you'll need to implement your "custom" interface somehow. This is easy (once again see the manual, you have to respect naming schemes so that Spring can wire interfaces and implementations at run time):

    public class UserRepositoryCustomImpl implements UserRepositoryCustom {
        @Autowired protected ElasticsearchTemplate elasticsearchTemplate;
    
        public List<User> findFuzzyByLastNameAndFirstName(String firstName, String lastName) {
            Criteria c = new Criteria("firstName").fuzzy(firstName).and(new Criteria("lastName").fuzzy(lastName));
            return elasticsearchTemplate.queryForList(new CriteriaQuery(c), CandidateEntity.class);
        }
    }
    

    Recompile, relaunch, and you should be able to have your repository do the fuzzy search like so.

    Then again (see the questions comments), you might also want to define the query as a String and you wouldn't need custom implementations. This is up to you.