Home > Blockchain >  How to search for specific word and exact match in ElasticSearch
How to search for specific word and exact match in ElasticSearch

Time:09-16

sample data for title

actiontype test
booleanTest
test-demo
test_demo
Test new account object
sync accounts data test

default Mapping for title

"title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
 },

tried with this query search

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "test"
          }
        }
      ]
    }
  },
}

here my expectation

with specific word(e.g. : test ) it should return following titles

expect
        actiontype test
        booleanTest
        test-demo
        test_demo
        Test new account object
        sync accounts data test

But

got
            actiontype test
            test-demo
            test_demo
            Test new account object
            sync accounts data test

With exact match (e.g. : sync accounts data test ) it should return only this(sync accounts data test) but got all records those contains this words (sync,account,data,test).

What should I do to make this happen ? Thanks.

CodePudding user response:

I am not sure which ES version you're using but the following should give you an idea.

  1. Using your mapping you can get all title text with test, including booleanTest using query string query type. Eg.
GET {index-name}/{mapping}/_search
{
  "query": {
    "query_string": {
      "default_field": "title",
      "query": "*test*"
    }
  }
}

However, for this to work, make sure you give your title field an analyzer with a lowercase analyzer filter (see below settings example). Your current mapping will not work since it's just pure text as is... test /= TEST by default.

  1. There are other ways, if you're interested to know the workings of ES... Eg. You can also match booleanTest in your match query by writing a custom nGram filter to your index settings. Something like,
{
  "index": {
    "settings": {
      "index": {
        "analysis": {
          "filter": {
            "nGram": {
              "type": "nGram",
              "min_gram": "2",
              "max_gram": "20"
            }
          },
          "ngram_analyzer": {
            "filter": [
              "lowercase",
              "nGram"
            ],
            "type": "custom",
            "tokenizer": "standard"
          }
        }
      }
    }
  }
}

NB: ngram_analyzer is just a name. You can call it whatever. min_gram & max_gram: Pick numbers that work for you.

Learn more about n-gram filter, the goods and bad here: N-GRAM

Then you can add the analyzer to your field mapping like,

{
  "title": {
    "type": "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256,
        "analyzer": "ngram_analyzer"
      }
    }
  }
}

Lastly for exact matches, these work on type keyword. So based on your mapping, you already have the keyword field so you can use term query to get the exact match by searching on the title.keyword field;

GET {index-name}/{mapping}/_search
{
  "query": {
    "term": {
      "title.keyword": {
        "value": "sync accounts data test"
      }
    }
  }
}

Also, you will want to read/ learn more about these solutions and decide on the best solution based on your indexing setup and needs. Also, there may be more ways to achieve what you need, this should be a good start.

  • Related