ElasticSearch -搜索字符串中的部分文本

4smxwvx5  于 2022-11-02  发布在  ElasticSearch
关注(0)|答案(2)|浏览(216)

使用ElasticSearch在String中搜索精确的部分文本的最佳方法是什么?
在SQL中,该方法为:%部分文本%,%文章文本%
在ElasticSearch中,当前使用的方法:

{
    "query": {
        "match_phrase_prefix": {
             "name": "PARTIAL TEXT"
        }
    }
}

但是,每当您删除字符串的第一个和最后一个字符时,它就会中断,如下所示(未找到结果):

{
    "query": {
        "match_phrase_prefix": {
             "name": "ARTIAL TEX"
        }
    }
}
ogsagwnx

ogsagwnx1#

我相信会有很多的建议,比如使用ngram分析器,关于如何解决这个问题。我相信最简单的是使用模糊。

{
  "query": {
    "match": {
      "name": {
        "query": "artial tex",
        "operator": "and",
        "fuzziness": 1
      }
    }
  }
}
xesrikrc

xesrikrc2#

有多种方法可以进行部分搜索,每种方法都有自己的权衡。

第一个字符串

对于通配符,在“关键字”字段而不是“文本”字段上执行搜索。

{
  "query": {              
          "wildcard": {
            "name.keyword": "*artial tex*"          
        }
   }
}

通配符的性能较差,但有更好的替代方案。
2.匹配/匹配短语/匹配短语前缀

如果您正在搜索整个标记,如“PARTIAL TEXT”。您可以简单地使用匹配查询,所有包含标记“PARTIAL”和“TEXT”的文档将被返回。
如果标记的顺序很重要,则可以使用match_phrase。
如果要搜索部分标记,请使用match_phrase_prefix。前缀匹配仅在搜索输入中的最后一个标记上完成,例如“partial tex”
这并不适合您的用例,因为您希望在任何地方进行搜索。


ngram标记器首先将文本分解为单词,然后发出每个单词的N-gram,每个单词的长度为指定的长度。
N元语法就像一个滑动窗口,可以在单词(指定长度的连续字符序列)上移动。它们对于查询不使用空格或具有较长复合词的语言(如德语)非常有用。

查询

{
  "settings": {
    "max_ngram_diff" : "5",
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 5,
          "max_gram": 7
        }
      }
    }
  }
}

POST index29/_analyze
{
  "analyzer": "my_analyzer",
  "text": "Partial text"
}

生成的令牌:

"tokens" : [
    {
      "token" : "Parti",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "Partia",
      "start_offset" : 0,
      "end_offset" : 6,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "Partial",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "artia",
      "start_offset" : 1,
      "end_offset" : 6,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "artial",
      "start_offset" : 1,
      "end_offset" : 7,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "artial ",
      "start_offset" : 1,
      "end_offset" : 8,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "rtial",
      "start_offset" : 2,
      "end_offset" : 7,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "rtial ",
      "start_offset" : 2,
      "end_offset" : 8,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "rtial t",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "tial ",
      "start_offset" : 3,
      "end_offset" : 8,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "tial t",
      "start_offset" : 3,
      "end_offset" : 9,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "tial te",
      "start_offset" : 3,
      "end_offset" : 10,
      "type" : "word",
      "position" : 11
    },
    {
      "token" : "ial t",
      "start_offset" : 4,
      "end_offset" : 9,
      "type" : "word",
      "position" : 12
    },
    {
      "token" : "ial te",
      "start_offset" : 4,
      "end_offset" : 10,
      "type" : "word",
      "position" : 13
    },
    {
      "token" : "ial tex",
      "start_offset" : 4,
      "end_offset" : 11,
      "type" : "word",
      "position" : 14
    },
    {
      "token" : "al te",
      "start_offset" : 5,
      "end_offset" : 10,
      "type" : "word",
      "position" : 15
    },
    {
      "token" : "al tex",
      "start_offset" : 5,
      "end_offset" : 11,
      "type" : "word",
      "position" : 16
    },
    {
      "token" : "al text",
      "start_offset" : 5,
      "end_offset" : 12,
      "type" : "word",
      "position" : 17
    },
    {
      "token" : "l tex",
      "start_offset" : 6,
      "end_offset" : 11,
      "type" : "word",
      "position" : 18
    },
    {
      "token" : "l text",
      "start_offset" : 6,
      "end_offset" : 12,
      "type" : "word",
      "position" : 19
    },
    {
      "token" : " text",
      "start_offset" : 7,
      "end_offset" : 12,
      "type" : "word",
      "position" : 20
    }
  ]

您可以对生成的任何令牌进行搜索。您也可以使用“token_chars”:[“letter”,“digit”]生成不包括空格的标记。
以上选项的选择将取决于数据大小和性能要求。通配符更灵活,但匹配是在运行时完成的,因此性能较慢。如果数据大小很小,这将是理想的解决方案。
Ngrams,标记是在索引时生成的。它占用更多的内存,但搜索速度更快。对于大数据量,这应该是理想的解决方案。

相关问题