【问题标题】:Elasticsearch Full text search and exact matchElasticsearch 全文搜索和精确匹配
【发布时间】:2018-06-04 09:44:48
【问题描述】:

Elasticsearch 映射

PUT testindex
{
  "settings": {
    "analysis": {
            "filter": {},
            "tokenizer": {
              "my_tokenizer": {
                  "type": "ngram",
                  "min_gram": 3,
                  "max_gram": 3,
                  "token_chars": []
                }
            },
            "analyzer": {
                "my_analyzer": {
                  "tokenizer": "my_tokenizer",
                  "filter": ["lowercase"]
                },
                "hiphen_analyzer": {
                    "tokenizer": "whitespace",
                    "filter": ["lowercase"]
                }
            }
        }
  },
    "mappings": {
      "test": {
        "properties": {
          "catch_all": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "store": true,
                            "ignore_above": 256
                        },
                        "raw": {
                            "type": "text",
                            "store": true,
                            "analyzer": "hiphen_analyzer",
                            "search_analyzer": "whitespace"
                        },
                        "ngrams": {
                          "type": "text",
                          "store": true,
                          "analyzer": "my_analyzer"
                        }
                    }
          },
          "hostname": {
            "type": "text",
            "copy_to": "catch_all"
          }
        }
      }
    }
}

文件

POST testindex/test
{
"hostname": "server-testing-01"
}
POST testindex/test
{
"hostname": "Dell Poweredge 111"
}

我有诸如“server-testing-01”、“server-testing-02”、“Dell Poweredge Server”之类的服务器主机名。

在 elasticsearch 中创建了一个映射,其中一个名为 hostname 的字段为“text”,copy_to 字段为“catch_all”。

目前只有一个字段“主机名”,但其他字段也将复制到 catch_all 字段。

有一个全局搜索框可帮助客户搜索这些主机名和其他数据。

  1. 当搜索“test”时,结果应该有“server-testing-01”、“server-testing-02”。当搜索“power”时,结果应该有“Dell Poweredge Server”。搜索“edge”时,结果应为“Dell Poweredge Server”
  2. 当搜索确切的“server-testing-01”结果时,应该只包含一个结果。

编辑: 目前尝试了 ngram 自定义分析器,它为某些部分搜索提供了正确的结果,而不是全部。

有人可以在elasticsearch中如何实现部分搜索和精确搜索吗?

【问题讨论】:

    标签: elasticsearch full-text-search n-gram


    【解决方案1】:

    由于您已经解决了第一点,因此实现第二点的最简单方法是将现有查询包装在布尔查询中,并将现有查询和新术语查询放入带有 minimum_should_match 1 的 should 子句中。这样,它将为您提供第二种选择。如果您需要一个工作示例,您需要提供您的映射、一个或两个文档作为示例,并且您的查询就是现在。

    您的用例非常广泛。您可以放置​​所有可能的分析器,但仍然会遗漏一些东西。我相信您并不真的需要所有这些分析器或任何复杂的查询。下面的内容非常简单(尽管需要注意性能)。

    PUT testindex
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "keyword_lowercase": {
              "tokenizer": "keyword",
              "filter": [
                "lowercase"
              ]
            }
          }
        }
      },
      "mappings": {
        "test": {
          "properties": {
            "hostname": {
              "type": "text",
              "analyzer": "keyword_lowercase"
            }
          }
        }
      }
    }
    
    GET testindex/_search
    {
      "query": {
        "wildcard": {
          "hostname": {
            "value": "*test*"
          }
        }
      }
    }
    
    GET testindex/_search
    {
      "query": {
        "wildcard": {
          "hostname": {
            "value": "*dell*power*"
          }
        }
      }
    }
    
    GET testindex/_search
    {
      "query": {
        "wildcard": {
          "hostname": {
            "value": "*edge*"
          }
        }
      }
    }
    

    一般而言,您可以使用 edge-ngram,但这不会涵盖 edge 示例,因为它们是从头开始的。您可以使用 ngrams,但 max 3 是不够的,您可能会错过某些情况。 使用这种方法,您几乎涵盖了所有内容。您需要在应用程序级别上做的是针对给定的输入 1.小写 2.用通配符包装输入

    例子:

    • Dell -> *dell*
    • SERVER -> *server*
    • DELL POWER -> *dell power*

    请小心,尽管您仍然会错过某些情况 示例:

    • server testing -> *server testing*

    以上行不通。如果你需要它工作,那么你可以在每个空格上添加一个通配符,那么上面就变成了这个

    • server testing -> *server*testing* 会起作用的

    这种方法将使您的索引更小,但您会在搜索期间付出代价,具体取决于您的数据大小和请求量。 不过你可以试一试。

    一般来说,通配符查询有点核,所以要小心行事。 另一种方法是增加你的 ngram 的最大值,但这会大大增加你的索引。我真的不知道你的情况,所以……你自己看看吧。

    【讨论】:

    • 请找到添加的映射。对于案例 1,有些结果有效,有些失败。你能帮忙吗?
    • 我已经编辑了我的回复。我相信通配符查询会更适合您的需求。这是最简单的方法
    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 2023-03-28
    • 1970-01-01
    • 2019-04-03
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    相关资源
    最近更新 更多