【问题标题】:Search full and partial text value using wildcard from elasticsearch使用来自 elasticsearch 的通配符搜索全部和部分文本值
【发布时间】:2020-05-21 16:00:13
【问题描述】:

我有下面的简单表格,其中包含来自 elasticsearch 的标题和代码列,如下所示

{ title: 'test1', code: 'ZjS3d3k8z',... },
{ title: 'test2 with more words', code: 'AjS3d2k1z',... }

我正在尝试使用通配符过滤标题和代码,如下所示,

{
  "sort": [
    {
      "creation_date": {
        "order": "desc"
      }
    },
    "_score"
  ],
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "account_id": 100
          }
        }
      ],
      "should": [
        {
          "wildcard": {
            "code": "?test2 with"
          }
        },
        {
          "wildcard": {
            "title": "*test2 with*"
          }
        }
      ],
      "minimum_number_should_match": 1
    }
  }
}

上述查询适用于预期结果/失败,但在以下情况下没有结果

> 'test1' <---- works(return expected result) when i try to search single word
> 'test2' <---- works(return expected result) when i try to search single word
> 'test2 with'<---- fails(return empty result) when i try to search more than one word with space'
> 'test2 with more words' <---- fails(return empty result) when i try to search full title

当我尝试如下搜索代码时,它总是返回空结果!!!

"should": [
        {
          "wildcard": {
            "code": "?ZjS3d3k8z"
          }
        },
        {
          "wildcard": {
            "title": "*ZjS3d3k8z*"
          }
        }
      ]

我想使用 elasticsearch 从数百万条记录中搜索具有部分/全部价值的标题/代码。请多多指教。

【问题讨论】:

  • 你能解释一下你所说的失败和工作是什么意思吗?是查询没有给你预期的结果还是导致一些错误。请添加所有不同类型的输入和预期输出组合。
  • Opster,现在更新了问题。上面的查询适用于某些具有预期结果的情况和某些没有结果的情况

标签: javascript node.js elasticsearch nosql


【解决方案1】:

对于通配符,在 "keyword" 字段而不是 "text" 上执行搜索。对于文本数据类型,分析字符串,分解为标记,同时按原样存储关键字字段。 "test2 with more words" 存储为 ["test2","with","more","words"] 并且您的通配符输入与这些标记匹配,因此不返回任何文档。

{
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "code.keyword": "*test2 with*"
          }
        },
        {
          "wildcard": {
            "title.keyword": "*test2 with*"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

使用动态模板创建的映射具有每种文本类型的关键字子字段。如果您已显式创建映射,则需要添加关键字子字段

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

通配符性能较差,有更好的替代方案。

  1. Match/Match_phrase/Match_phrase_prefix

如果您正在搜索诸如“test2 with”之类的整个标记。您可以简单地进行匹配查询,将返回所有包含标记“test2”和“with”的文档

"should": [
        {
          "match": {
            "code": {
              "query": "test2 with",
              "operator": "and"
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "test2 with",
              "operator": "and"
            }
          }
        }
      ]

如果令牌的顺序很重要,您可以使用 match_phrase。

如果要搜索部分标记,请使用 match_phrase_prefix。 前缀匹配仅在搜索输入 ex 中的最后一个标记上完成。 "test2 w"

  1. Edge N grams

edge_ngram 标记器首先将文本分解为单词 遇到指定字符列表之一,然后发出 每个单词的 N-gram,其中 N-gram 的开头锚定到 单词的开头。

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}

生成的令牌:

"tokens" : [
    {
      "token" : "te",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "tes",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "test",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "test2",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "wi",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "wit",
      "start_offset" : 6,
      "end_offset" : 9,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "with",
      "start_offset" : 6,
      "end_offset" : 10,
      "type" : "word",
      "position" : 6
    }
  ]

这将让您像“tes wit”一样执行搜索,即任何标记都可以是部分的,不像 match_phrase_prefix 只对最后一个标记进行前缀搜索

  1. N Grams

ngram 分词器首先将文本分解为单词 遇到指定字符列表之一,然后发出 指定长度的每个单词的 N-gram。

N-gram 就像一个在单词上移动的滑动窗口 - 指定长度的连续字符序列

即使中间的“est”匹配测试,你也可以搜索部分标记

  1. Suggesters 它们在您键入时提供搜索功能

您可以根据自己的要求选择其中任何一种

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 2013-09-11
    • 2017-12-03
    • 2014-08-12
    • 2022-10-15
    相关资源
    最近更新 更多