0

I have students information placed in Elastic search db. I am trying to perform a search

  1. Fetch all the records where the student grade is "A"

     {
        "query":{
           "bool":{
              "must":[
                 {
                    "match":{
                       "grade":{
                          "query":"A",
                          "operator":"OR",
                          "prefix_length":0,
                          "max_expansions":50,
                          "fuzzy_transpositions":true,
                          "lenient":false,
                          "zero_terms_query":"NONE",
                          "auto_generate_synonyms_phrase_query":true,
                          "boost":1.0
                       }
                    }
                 }
              ],
              "adjust_pure_negative":true,
              "boost":1.0
           }
        }
     }
    
  2. Fetch all the records where the city value begins with B*

     {
        "query":{
           "bool":{
              "must":[
                 {
                    "regexp":{
                       "city":{
                          "value":"B*",
                          "flags_value":65535,
                          "max_determinized_states":10000,
                          "boost":1.0
                       }
                    }
                 }
              ],
              "adjust_pure_negative":true,
              "boost":1.0
           }
        }
     }
    
  3. For generating search query

     SearchSourceBuilder elasticSearchSourceBuilder = new SearchSourceBuilder();
     BoolQueryBuilder esQueryBuilder = QueryBuilders.boolQuery();
     Map<String,List<String>> searchCriteriaMap = new HashMap();
     searchCriteriaMap.put("grade", Arrays.asList(new String[] {"A"}));
     for(Map.Entry<String, List<String>> entry :searchCriteriaMap.entrySet()) {
         List<String> parameterValueList = searchCriteriaMap.get(entry.getKey());
         String parameterValue = String.join(",", parameterValueList);
         MatchQueryBuilder matchQueryBuilder= QueryBuilders.matchQuery(entry.getKey(), parameterValue);
    
         esQueryBuilder.must(matchQueryBuilder);
    
     }
    
  4. For Generating regular Expression query:

     SearchSourceBuilder elasticSearchSourceBuilder = new SearchSourceBuilder();
     BoolQueryBuilder esQueryBuilder = QueryBuilders.boolQuery();
     Map<String,List<String>> searchCriteriaMap = new HashMap();
     searchCriteriaMap.put("city", Arrays.asList(new String[] {"Bangalore*"}));
     //queryParameterMap1.put("school.name", Arrays.asList(new String[] {"Joseph"}));
     for(Map.Entry<String, List<String>> entry :searchCriteriaMap.entrySet()) {  
         RegexpQueryBuilder matchQueryBuilder= QueryBuilders.regexpQuery("city", "Bang*");
         esQueryBuilder.must(matchQueryBuilder);
    
     }
    

How do I handle both these conditions in a single query, that is the student whose grade is A and the city value should begin with B*. For generating the query, I have used Java Elastic search query Builder.

The student records are:

{
   "name":"Anthon",
   "id":"JO-01",
   "courses":[
      "English",
      "Science",
      "Mathematics",
      "Physics",
      "Biology"
   ],
   "grade":"A",
   "cgpa":8.3,
   "schoolName":"Joseph Higher Seconday School",
   "city":"Bangalore",
   "dateOfJoining":"Jul 24, 3914 12:00:00 AM"
}
User27854
  • 824
  • 1
  • 16
  • 40

1 Answers1

1

You can just combined the must clause of both queries

Query:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "grade": {
              "query": "A"
            }
          }
        },
        {
          "regexp": {
            "city.keyword": {
              "value": "B.*"
            }
          }
        }
      ]
    }
  }
}

Java Code:

SearchSourceBuilder elasticSearchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder esQueryBuilder = QueryBuilders.boolQuery();
MatchQueryBuilder matchQueryBuilder= QueryBuilders.matchQuery("grade", "A");
RegexpQueryBuilder regxQueryBuilder= QueryBuilders.regexpQuery("city", "B*");
esQueryBuilder.must(matchQueryBuilder);
esQueryBuilder.must(regxQueryBuilder);
System.out.println(esQueryBuilder.toString());

Here, if you are using multi-field then you need to give city.keywordand you need to pass query same as value of field like B.* and if you define city field as text then you need to use city as field name and value as b.*

Sagar Patel
  • 4,993
  • 1
  • 8
  • 19
  • Sorry for the delayed response Thanks for the detailed explanation. I have one doubt, you have mentioned that, we need to be aware of the field type before hand. Unfortunately, in my case we can use this regular expression on various fields some of the fields are declared as text and some as defined as keyword. How do I handle in such scenarios? – User27854 Mar 10 '22 at 13:11
  • 1
    you can keep text field as it and for keyword field you can specify `normalizer` so it will work for lowercase as well. just please check normalizer documentation for your specific ES version. – Sagar Patel Mar 10 '22 at 13:18
  • 1
    Please check [this](https://stackoverflow.com/questions/63292555/how-to-do-a-case-insensitive-search-on-a-keyword-field-in-elasticsearch-without) post , it will give you more clear understanding. – Sagar Patel Mar 10 '22 at 13:21