2
votes

This works like a charm :

        Client client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("localhost", 9300));

        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("field", "word_1");
        fuzzyQueryBuilder.fuzziness(Fuzziness.AUTO);

        SearchResponse response = client.prepareSearch("ts_index")
                                        .setTypes("service")
                                        .setQuery(fuzzyQueryBuilder)
                                        .setFrom(0).setSize(60).setExplain(true)
                                        .execute()
                                        .actionGet();
        SearchHit[] results = response.getHits().getHits();

But if I want to search by multiple words, it returns nothing, Ex :

FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("field", "word_1 word_2");

When I'm using CURL, I've resolved this issue by adding operator to my JSON attributes:

curl -XGET "http://localhost:9200/_search" -d" {\"query\":{\"match\":{\"field\":{\"query\":\"word_1 word_2\",\"fuzziness\":\"AUTO\",\"operator\":\"and\"}}}}

How can I achieve this in Java ?

2
means that the multiple words are in one String and will be splitted with a space? ("field", "word_1<space?> word_2")Patrick
just have a look to my answer. Maybe this can help you. And just leave a comment if there is a need for more explanation.Patrick

2 Answers

2
votes

I believe this is possible with must for AND and should for OR:

 QueryBuilder qb = QueryBuilders.boolQuery()
                .must(QueryBuilders.fuzzyQuery("field", "word_1"))
                .must(QueryBuilders.fuzzyQuery("field", "word_2"));
1
votes

You can try to build this in a dynamic way with an enum:

 public enum MultiQueryBuilder {

  OPERATOR_AND {
    @Override
    public QueryBuilders createQuery(String field, String multiWord) {
    String[] words = multiWord.split("\\s+");
    QueryBuilder queryBuilder = QueryBuilder.boolQuery();
    for(String word : words){
     queryBuilder.must(QueryBuilders.fuzzyQuery(field, word));
    }    
    return queryBuilder;
},

 OPERATOR_OR {
    @Override
    public QueryBuilders createQuery(String field, String multiWord) {
    String[] words = multiWord.split("\\s+");
    QueryBuilder queryBuilder = QueryBuilder.boolQuery();
    for(String word : words){
     queryBuilder.should(QueryBuilders.fuzzyQuery(field, word));
    }    
 return queryBuilder;
};

 public abstract Querybuilders createQuery(String field, String multiWord);
}

You just have to call it in this way:

FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders
    .fuzzyQuery(MultiQuerybuilder
    .valueOf(OPERATOR_AND)
    .createQuery("field", "word_1 word_2"));