【问题标题】:Elasticsearch - Fuzzy search not giving suggestionsElasticsearch - 模糊搜索不提供建议
【发布时间】:2020-06-18 20:41:25
【问题描述】:

我正在尝试通过 NodeJS 在 Elasticsearch 中实现模糊/自动完成搜索。我已经按索引"artist" 对数据进行了索引。这是 ES 中存储数据的示例。

{
  "hits": [{
    "_index": "artist",
    "_type": "_doc",
    "_id": "EyejqnAB2pHGVJHwV53Q",
    "_score": 1,
    "_source": {
      "kind": "song",
      "artistId": 111051,
      "artistName": "Eminem",
      "trackName": "Crack a Bottle (feat. Dr. Dre & 50 Cent)",
      "collectionName": "Relapse (Deluxe Version)",
      "collectionCensoredName": "Relapse (Deluxe Version)",
      "artistViewUrl": "https://music.apple.com/us/artist/eminem/111051?uo=4",
      "collectionViewUrl": "https://music.apple.com/us/album/crack-a-bottle-feat-dr-dre-50-cent-feat-dr-dre-50-cent/1440558626?i=1440558826&uo=4",
      "trackViewUrl": "https://music.apple.com/us/album/crack-a-bottle-feat-dr-dre-50-cent-feat-dr-dre-50-cent/1440558626?i=1440558826&uo=4",
      "previewUrl": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview128/v4/da/a5/c1/daa5c140-2c3d-1f74-40c3-b6e596e52b82/mzaf_7480202713407880256.plus.aac.p.m4a",
      "artworkUrl100": "https://is1-ssl.mzstatic.com/image/thumb/Music128/v4/c5/f8/fd/c5f8fdf6-d4c9-85c9-d169-c5d349a44f1c/source/100x100bb.jpg",
      "collectionPrice": 12.99,
      "releaseDate": "2009-02-02T12:00:00Z",
      "collectionExplicitness": "explicit",
      "trackExplicitness": "explicit",
      "discCount": 1,
      "discNumber": 1,
      "trackCount": 24,
      "trackNumber": 18,
      "country": "USA",
      "currency": "USD"
    }
  }]
}

artistName 上方的值为Eminem,问题是当我输入'e' 时,它不显示任何内容,'em'emiemin 相同。当我输入emine 然后它开始给出结果。我哪里错了?

【问题讨论】:

  • 您有没有机会仔细阅读答案并尝试我建议的方法?
  • 如果你想返回结果,因为第一个字符你可以使用 simplequerystring 在输入字符串的尾部附加 *。 elastic.co/guide/en/elasticsearch/reference/current/…
  • @JordiJordi,这会导致通配符查询,这是非常昂贵的,即使使用我的prefix 查询方法也可以实现同样的事情,但我不鼓励只使用 1 个字符,你不要'无法获得高质量的结果及其非常昂贵的结果,请参阅我的回答中的博客,其中更详细地解释了这些权衡
  • @opster-elasticsearch-ninja 我同意,最好使用前缀查询
  • @JordiJordi,酷 :)

标签: javascript node.js typescript elasticsearch elasticsearch-5


【解决方案1】:

Match query 返回与提供的文本、数字、日期或布尔值匹配的文档。在匹配之前分析提供的文本。 ex text :"this is a test" 与标准分析器存储为 ["this","is", "a", "token"] 您正在搜索的文本也将被分解为标记,并且这些标记将被匹配。

Fuzziness:取单个词并查找字典中指定模糊度内的所有词。默认模糊度为 AUTO。

以下是 auto 的值 AUTO——它根据词条的长度生成一个编辑距离。对于长度: 0..2 -- 必须完全匹配 3..5 -- 允许一次编辑

5 -- 允许两次编辑

所以你可以搜索“emine”,因为编辑距离是 1

要实现自动完成,您可以使用 1. EdgeNgrams 2.完成建议

以上链接参考 1.AutoCompletion 2.Fuzziness

【讨论】:

  • 完成提示器仍在开发中,实施起来并不简单,从您列出的两种方法中可以看出,还有其他几种方法可以实现自动完成,其中一种刚刚在 7.2 中发布了 search-as-you-type 数据类型版本,用户还应该知道所有四种方法的权衡,以避免以后出现意外。详情请参考我的回答
  • 顺便说一句,我发表了一篇关于所有四种方法的详细博客opster.com/elasticsearch-glossary/…,请通过它深入了解大型和可扩展系统中的自动完成 esp,如果您有任何问题,请联系我。
  • 谢谢 :),顺便说一句,我不确定,为什么我不能在 SO cmets 中标记你:|
【解决方案2】:

实现自动补全功能有多种方式,但模糊搜索不正确(主要用于搜索相关文档wrt到tokens(de-dupe)和拼写检查参考this申请模糊搜索)。

在您的情况下,我建议使用prefix query,如果您的索引大小不是很大并将最小字符长度限制为两个,即不要搜索e 和仅当用户输入两个或多个字符(即ememiemin 等)时才显示搜索结果。

工作示例

索引映射

{
    "mappings": {
        "properties": {
            "artistName": {
                "type": "text"
            }
        }
    }
}

索引文档

{
   "artistName" : "Eminem"
}

{
   "artistName" : "Emiten"
}

搜索查询

{
    "query": {
        "prefix": {
            "artistName": {
                "value": "em"
            }
        }
    }
}

搜索结果

{
            "_index": "so-60558525-auto",
            "_type": "_doc",
            "_id": "1",
            "_score": 1.0,
            "_source": {
               "artistName": "Eminem"
            }
         },
         {
            "_index": "so-60558525-auto",
            "_type": "_doc",
            "_id": "2",
            "_score": 1.0,
            "_source": {
               "artistName": "Emiten"
            }
         }

重要阅读

您可以选择大致四种方法来实现自动完成,每种方法都有一些权衡,您应该注意证明您的功能性需求和非功能性需求是合理的(性能、维护、实施困难)。

【讨论】:

    猜你喜欢
    • 2016-08-25
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多