【问题标题】:Subsequence searching with elasticsearch使用 elasticsearch 进行子序列搜索
【发布时间】:2017-11-01 16:28:45
【问题描述】:

我在 Elasticsearch 中设置了一个简单的索引,我想对它执行 "Github like" 子序列搜索:

{
  "files" : {
    "aliases" : { },
    "mappings" : {
      "file" : {
        "properties" : {
          "name" : {
            "type" : "text",
            "analyzer" : "simple"
          }
        }
      }
    }
  }
}

然后我添加一个文档:

curl -XPOST 'localhost:9200/files/file' -H 'Content-Type: application/json' -d'
{
  "name": "/my/path/to/file.txt"
}
'

当我用

查询时

"query": { "match": {"name": {"query": "mypath", "fuzziness": "AUTO" }} }

我按预期取回了文件。但是,如果我查询

"query": { "match": {"name": {"query": "mypathto", "fuzziness": "AUTO" }} }

文件不再返回。


基本上我希望文档的所有子序列都匹配,例如:

  • mat/t => /my/path/to/file.t xt
  • mx => /my/path/to/file.txt
  • mypathtofiletxt => /我的/路径//file.txt

【问题讨论】:

  • 您是否尝试使用“*”,同时使用query_string 查询“*mypath*”。你应该使用高亮功能。
  • 我会在这里使用多个字段。除了您拥有的“名称”字段之外,您还可以添加更多字段。例如:带有模式过滤器的 nGram 字段以删除“/”。您可以根据您的用例配置 nGram 长度。查询所有字段(例如:“name”和“name.ngram”)。使用自己的分析器添加尽可能多的字段。阅读:elastic.co/guide/en/elasticsearch/reference/current/…
  • 正如@Ivan 在他的回答中解释的那样,使用简单/标准分析器在名称字段上使用模糊不会让您走得太远,您的用例。

标签: elasticsearch search fuzzy-search


【解决方案1】:

关于长期

简单分析器将您的文件名拆分为一组小标记:

curl -XPOST "http://localhost:9200/test/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "simple",
  "text": "/my/path/to/file.txt"
}'

这意味着您的索引中有以下术语 ["my","path", "to", "file","txt"]

匹配查询接受文本并使用与索引时相同的分析器对其进行分析,即:

curl -XPOST "http://localhost:9200/test/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "simple",
  "text": "mypathto"
}'

因此,在您的情况下,匹配查询会尝试查找 ma​​pathto 术语。这适用于小名称,因为模糊查询通过术语 path 匹配您的短语 mypath,没有 2 个符号(2 个版本)mypath。作为解决方案,您可以使用以下查询:

curl -XGET "http://localhost:9200/test/_search" -H 'Content-Type: application/json' -d'
{
  "query": { "match": {"name": {"query": "/my/path/to", "fuzziness": "AUTO" }} }
}'

GitHub 点赞查询

对此没有开箱即用的解决方案,但您可以执行以下操作:

  1. 索引字段作为关键字 - 不分析 = 保持原样
  2. 只使用小写规范器(不是分析器)
  3. 在每个符号之间使用带 * 的通配符查询

请注意,通配符查询可能会很慢,因为它需要迭代许多术语(内部它使用http://www.brics.dk/automaton/,这对于小型索引来说是非常优化和快速的),因此性能取决于具有相似性的唯一术语的数量子序列。为了优化性能,您可以为每个项目使用唯一索引。这是一个简单的例子:

PUT test
{
  "settings": {
    "analysis": {
      "normalizer": {
        "lowercase_normalizer": {
          "type": "custom",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "file": {
      "properties": {
        "name": {
          "type": "keyword",
          "normalizer": "lowercase_normalizer"
        }
      }
    }
  }
}

PUT test/file/1
{
  "name": "/my/path/to/file.txt"
}

GET test/_search
{
  "query": { "wildcard": {"name": {"value": "*m*a*t*/*t*"}} }
}

GET test/_search
{
  "query": { "wildcard": {"name": {"value": "*m*x*"}} }
}


GET test/_search
{
  "query": { "wildcard": {"name": {"value": "*m*y*p*a*t*h*t*o*f*i*l*e*t*x*t*"}} }
}

另请注意,通配符查询不支持分析器/normalyzers,因此您必须在客户端请求小写。

【讨论】:

  • 这完全是另一个搜索。我需要mypathmypathto /my/path/to 来匹配文档。就像你在问题的 Github 链接中输入 clsroelbenchtrtaskjava 一样,你会得到 https://github.com/elastic/elasticsearch/blob/master/client/benchmark/src/main/java/org/elasticsearch/client/benchmark/transport/TransportClientBenchmark.java 作为结果,因为它包含所有给定的字符以相同的顺序。
  • @OskarPersson 这个怎么样?
猜你喜欢
  • 2017-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 2019-04-25
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
相关资源
最近更新 更多