Extract keywords (multi word) from text using elastic search

前端 未结 1 1785
孤街浪徒
孤街浪徒 2021-01-19 07:10

I have an index full of keywords and based on those keywords I want to extract the keywords from the input text.

Following is the sample keyword index. Please note t

相关标签:
1条回答
  • 2021-01-19 08:00

    There's just one real way to do this. You'll have to index your your data as keywords and search it analyzed with shingles:

    See this reproduction:

    First, we'll create two custom analyzers: keyword and shingles:

    PUT test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer_keyword": {
              "type": "custom",
              "tokenizer": "keyword",
              "filter": [
                "asciifolding",
                "lowercase"
              ]
            },
            "my_analyzer_shingle": {
              "type": "custom",
              "tokenizer": "standard",
              "filter": [
                "asciifolding",
                "lowercase",
                "shingle"
              ]
            }
          }
        }
      },
      "mappings": {
        "your_type": {
          "properties": {
            "keyword": {
              "type": "string",
              "index_analyzer": "my_analyzer_keyword",
              "search_analyzer": "my_analyzer_shingle"
            }
          }
        }
      }
    }
    

    Now let's create some sample data using what you gave us:

    POST /test/your_type/1
    {
      "id": 1,
      "keyword": "thousand eyes"
    }
    POST /test/your_type/2
    {
      "id": 2,
      "keyword": "facebook"
    }
    POST /test/your_type/3
    {
      "id": 3,
      "keyword": "superdoc"
    }
    POST /test/your_type/4
    {
      "id": 4,
      "keyword": "quora"
    }
    POST /test/your_type/5
    {
      "id": 5,
      "keyword": "your story"
    }
    POST /test/your_type/6
    {
      "id": 6,
      "keyword": "Surgery"
    }
    POST /test/your_type/7
    {
      "id": 7,
      "keyword": "lending club"
    }
    POST /test/your_type/8
    {
      "id": 8,
      "keyword": "ad roll"
    }
    POST /test/your_type/9
    {
      "id": 9,
      "keyword": "the honest company"
    }
    POST /test/your_type/10
    {
      "id": 10,
      "keyword": "Draft kings"
    }
    

    And finally query to run search:

    POST /test/your_type/_search
    {
      "query": {
        "match": {
          "keyword": "I saw the news of lending club on facebook, your story and quora"
        }
      }
    }
    

    And this is result:

    {
      "took": 6,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 4,
        "max_score": 0.009332742,
        "hits": [
          {
            "_index": "test",
            "_type": "your_type",
            "_id": "2",
            "_score": 0.009332742,
            "_source": {
              "id": 2,
              "keyword": "facebook"
            }
          },
          {
            "_index": "test",
            "_type": "your_type",
            "_id": "7",
            "_score": 0.009332742,
            "_source": {
              "id": 7,
              "keyword": "lending club"
            }
          },
          {
            "_index": "test",
            "_type": "your_type",
            "_id": "4",
            "_score": 0.009207102,
            "_source": {
              "id": 4,
              "keyword": "quora"
            }
          },
          {
            "_index": "test",
            "_type": "your_type",
            "_id": "5",
            "_score": 0.0014755741,
            "_source": {
              "id": 5,
              "keyword": "your story"
            }
          }
        ]
      }
    }
    

    So what it does behind the scenes?

    1. It indexes your documents as whole keywords (It emits whole string as a single token). I've also added asciifolding filter, so it normalizes letters, i.e. é becomes e) and lowercase filter (case insensitive search). So for instance Draft kings is indexed as draft kings
    2. Now search analyzer is using same logic, except that its' tokenizer is emitting word tokens and on top of that creates shingles(combination of tokens), which will match your keywords indexed as in first step.
    0 讨论(0)
提交回复
热议问题