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?
You could use something like this :
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 :
{
"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:
"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);