Search elastic4s search query mode

The previous article mentioned that query mode not only filters the records, but also scores the records that meet the conditions, that is, the similarity matching degree with the conditions. We'll discuss ratings in the blog post that follows, and we'll only cover query queries in this article.

Query can be divided into absolute value query and full-text query: absolute value query refers to the query of non text type fields, and full-text query generally refers to the query of text fields. If you need to query the absolute value of the text field, you can use fields to define a keyword field under the text field. The text type field will be decomposed into many words by the word breaker processing when building index, and then the query target will go through the word segmentation processing before matching words one by one during query. Therefore, it should be noted that the entered query criteria are not necessarily the final query content, because word segmentation will be performed first.

Let's take a look at some absolute value query examples:

POST /bank/_search
{
  "query" : {
    "term" : {
       "state.keyword": "IL"
    }
  }
}
POST /bank/_search
{
  "query" : {
    "terms" : {
       "state.keyword": ["IL","WA"]
    }
  }
}
POST /bank/_search
{
  "query" : {
    "range" : {
       "age": {
         "gte" : 20,
         "lte" : 40
       }
    }
  }
}

POST /bank/_search
{
  "query" : {
    "prefix" : {
       "address.keyword": "880"
    }
  }
}
POST /bank/_search
{
  "query" : {
    "wildcard": {
       "address.keyword": "*Holmes*"
    }
  }
}
POST /bank/_search
{
  "query" : {
    "regexp": {
       "address.keyword": ".*Holmes.*"
    }
  }
}

elastic4s is expressed as follows:

 val qTerm = search("bank").query(termQuery("state.keyword","IL"))
  val qTerms = search("bank").query(termsQuery("state.keyword","IL","WA"))
  val qRange = search("bank").query(rangeQuery("age").gte(20).lte(40))
  val qPrefix = search("bank").query(prefixQuery("address.keyword","880"))
  val qWildcard = search("bank").query(wildcardQuery("address.keyword","*Holmes*"))
  val qRegex = search("bank").query(regexQuery("address.keyword",".*Holmes.*"))

The simplest example of full-text query is match query:

POST /bank/_search
{
  "query" : {
    "match" : { "address" : "holmes"}
  }
}

 val qMatch = search("bank").query(matchQuery("address","holmes"))

The above is a single word query demonstration. Multi word full text query is as follows:

POST /bank/_search
{
  "query" : {
    "match" : { "address" : "holmes lane"}
  }
}

 val qMMatch = search("bank").query(matchQuery("address","holmes lane"))

There is a problem: the query result includes not only 880 holes lane but also 685 School Lane. This is because the word breaker breaks down "holes lane" into two words: "holes" and "lane". The default relationship of multi word query is or. As long as there are holes, any item of Lane meets the conditions. We can use and to associate:

POST /bank/_search
{
  "query" : {
    "match" : { 
      "address" : {
        "query": "holmes lane",
        "operator": "and"
      }
    }
  }
}

  val qMMatchAnd = search("bank").query(matchQuery("address","holmes lane").operator("and"))

Now there's only 880 holes Lane left. The following query has the same effect:

POST /bank/_search
{
  "query" : {
    "match" : { 
      "address" : {
        "query": "holmes lane",
        "minimum_should_match": "100%"
      }
    }
  }
}

  val qMMatchMin = search("bank").query(matchQuery("address","holmes lane").minimumShouldMatch("100%"))

The above examples are simple type queries, that is, single statement queries. In reality, we generally need to use and,or to combine a variety of conditions to form a compound query. The most representative is boolQuery. The format of boolQuery is as follows:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [    // lastname=duke and gender.keyword = M
        { "match": { "lastname":   "duke" }},
        { "term": { "gender.keyword": "M" }}
      ],
      "must_not": [  // and firstname.keyword != Jackson and city.keyword != Jackson
        { "term": { "firstname.keyword":   "Jackson"}},
        { "term": { "city.keyword": "Brogan" }}
      ],
      "should": [  // or email.keyword = *.cn or age >= 80
        { "wildcard": { "email.keyword":   "*.cn" }},
        { "range": { "age": {"gte" : 80}}}
      ],    
      "filter": [  // filter state.keyword in (IL,WA,TA) and balance >= 100000
        { "terms":  { "state.keyword": ["IL","WA","TA"] }},
        { "range": { "balance": { "gte": 100000 }}}
      ]
    }
  }
}

In elastic4s:

  val qBool = search("bank").query(
    boolQuery().must(
      matchQuery("lastname","duke"),
      termQuery("gender.keyword","M")
    ).not(
      termQuery("fistname.keyword","Jackson"),
      termQuery("city.keyword","Brogan")
    ).should(
      termsQuery("state.keyword",Seq("IL","WA","TA")),
      rangeQuery("balance").gte(100000)
    )
  )

In the above example, the most, most no, should, and filter paragraphs can appear in boolQuery individually or jointly. You can also embed boolQuery in any paragraph, as follows:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "lastname":   "duke" }},
        { "term": { "gender.keyword": "M" }}
      ],
      "must_not": [
        { "term": { "firstname.keyword":   "Jackson"}},
        { "term": { "city.keyword": "Brogan" }}
      ],
      "should": [
        { "wildcard": { "email.keyword":   "*.cn" }},
        { "range": { "age": {"gte" : 80}}}
      ],    
      "filter": [
        { "terms":  { "state.keyword": ["IL","WA","TA"] }},
        { "range": { "balance": { "gte": 100000 }}},
        {
          "bool" : {
            "should" : [
               {"range" : {"balance" :{"gte" : 1000}}}
              ]
          }
        }
      ]
    }
  }
}

Tags: Scala

Posted on Mon, 27 Apr 2020 18:47:37 -0700 by gargoylemusic