How to query Elastic with Spring-data-elastic
Asked Answered
C

2

5

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!

Crossbill answered 30/9, 2016 at 11:25 Comment(5)
Have you had a look at docs.spring.io/spring-data/elasticsearch/docs/current/reference/… ? By the way, EntityManager is a JPA concept, not an elasticsearch one, so there's no point in searching in that direction.Mailemailed
You're correct, it's a JPA concept so it doesn't fit here. I have read the documentation you linked to, but I still do not know how to set it up to allow for fuzzy logic. Is it a query issue? An indexing issue? Do I need to change my domain entity?Crossbill
A quick search does not provide a way to have automatic fuzzy query generation from the method name, but you can always resort to criteria based ones or hand written.Mailemailed
Thanks @Mailemailed I'll take a closer look at Criteria. I was looking at them before, but I missed Criteria.fuzzy method.Crossbill
If I'm looking for a fuzzy search on firstName and lastName, I would assume there's a lot of examples out there, yet I cannot find a single one. Am I bad Googler or is this not something that many find hard?Crossbill
M
11

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.

Mailemailed answered 30/9, 2016 at 13:49 Comment(0)
C
4

You can also access the search engine via the @Query annotation:

public interface UserRepository extends ElasticsearchRepository<Users, String> {

@Query("{\"multi_match\": {\"query\": \"?0\", \"fields\": [\"firstName\", \"lastName\"], \"fuzziness\": \"AUTO\"}}")
Page<Users> find(String q, Pageable pageable);
}
Cassandracassandre answered 16/10, 2018 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.