spring-bootelasticsearchjhipsterelasticsearch-rest-client

How to write following elastic-search wildcard query in spring boot?


Database: Elasticsearch

Field Name: "tag"

Datatype: String

Question: How to perform a search in the tag field with a wildcard character?

I tried the following (in Kibana):

User Request: { "tag" : [ "Attendance", "Employee" ] }

POST test/_search
{
    "query":{
        "bool" : {
          "should" : [
            {"wildcard":{"tag.keyword": "*Attendance*" }},
            {"wildcard":{"tag.keyword": "*Employee*" }}
          ]
        }
    }
}

This worked successfully but I don't have an idea how to perform the same thing in spring boot.

I worked with following:

.should(wildcardQuery("tag.keyword", "Attendance"))

But this is just for a single field, I have a requirement for a dynamic field where user input should be different in size and value.

Can someone please guide me?


Solution

  • You could use something like this :

    Rest Highlevel client Query :

    SearchRequest searchRequest = new SearchRequest(<your-index-name>);
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
     QueryBuilder query =  QueryBuilders.boolQuery().should(new WildcardQueryBuilder("tag.keyword", "*Attendance*"))
                        .should(new WildcardQueryBuilder("tag.keyword", "*Employee*"));
    searchSourceBuilder.query(query);
    searchRequest.source(searchSourceBuilder);
    
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    

    Here client is the RestHighLevelClient bean that I have autowired in my class as follows :

    @Autowired
    private RestHighLevelClient client;
    

    and this bean I have defined in my config class as :

    @Bean(destroyMethod = "close")
    public RestHighLevelClient client() {
    
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(new HttpHost("localhost", 9200, "http")));
    
            return client;
    
    }
    

    This would construct query in this form :

    Query

        {
      "bool" : {
        "should" : [
          {
            "wildcard" : {
              "tag.keyword" : {
                "wildcard" : "*Attendance*",
                "boost" : 1.0
              }
            }
          },
          {
            "wildcard" : {
              "tag.keyword" : {
                "wildcard" : "*Employee*",
                "boost" : 1.0
              }
            }
          }
        ],
        "adjust_pure_negative" : true,
        "boost" : 1.0
      }
    }
    

    I have tested by creating index with same mapping as mentioned by you :

    Documents indexed :

      "_source": {
                "tag": "Attendance1"
        }
    
    
        "_source": {
                "tag": "1Employee"
        }
    
    
    
          "_source": { "tag": "*Employee*" }
    
    
        { "tag" : [ "Attendance", "Employee" ] }
    

    And when I search using above rest query , I got the following response:

    Response

    "hits": [
            {
                "_index": "test",
                "_type": "_doc",
                "_id": "4",
                "_score": 2.0,
                "_source": {
                    "tag": [
                        "Attendance",
                        "Employee"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "_doc",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "tag": "Attendance1"
                }
            },
            {
                "_index": "test",
                "_type": "_doc",
                "_id": "2",
                "_score": 1.0,
                "_source": {
                    "tag": "*Employee*"
                }
            },
            {
                "_index": "test",
                "_type": "_doc",
                "_id": "3",
                "_score": 1.0,
                "_source": {
                    "tag": "1Employee"
                }
            }
        ]
    

    Not sure what is meant by this part of your question:

    I have requirement for dynamic field where user input should be different in size and value.

    But, I am assuming it means from user you may get different tag list and based on that you want to create query.

    You can do something like this to achieve the same :

            // { "tag" : [ "Attendance", "Employee" ] } you can read this tag list though converter and pass it into list kind of data structure. Currently, I have created dummy list `tags` which has Attendance and Employee as items.
                List<String> tags = new ArrayList<>();
                tags.add("Attendance");
                tags.add("Employee");
    
                SearchRequest searchRequest = new SearchRequest(<your-index-name>);
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                List<WildcardQueryBuilder> wildcards = new ArrayList<WildcardQueryBuilder>();
    
                for(String tag :  tags) {
                    WildcardQueryBuilder wildcard =  new WildcardQueryBuilder("tag.keyword", "*" + tag + "*");
                    wildcards.add(wildcard);
    
                }
                BoolQueryBuilder boolQuery = new BoolQueryBuilder();
                for(WildcardQueryBuilder wildcard : wildcards) {
                    boolQuery.should(wildcard);
                }
    
                searchSourceBuilder.query(boolQuery);
                searchRequest.source(searchSourceBuilder);
    
                SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);