【问题标题】:case insensitive elasticsearch with uppercase or lowercase大小写不敏感的弹性搜索,大写或小写
【发布时间】:2017-02-21 19:24:20
【问题描述】:

我正在使用弹性搜索,但遇到了问题。如果有人给我提示,我将非常感激。

我想分析由不同条目组成的字段“名称”或“描述”。例如,有人想搜索 Sara。如果他进入 SARA、SAra 或 sara。他应该能够得到萨拉。 弹性搜索使用分析器,使所有内容都小写。

我想实现它不区分大小写,无论用户输入的名称是大写还是小写,他/她都应该得到结果。 我正在使用 ngram 过滤器来搜索名称和小写字母,这使得它不区分大小写。但是我想确保一个人即使输入大写或小写也能得到结果。

有没有办法在弹性搜索中做到这一点?

{"settings": {

        "analysis": {
            "filter": {
                "ngram_filter": {
                    "type": "ngram",
                    "min_gram": 1,
                    "max_gram": 80
                }
            },
            "analyzer": {
                "index_ngram": {
                    "type": "custom",
                    "tokenizer": "keyword",
                    "filter": [ "ngram_filter", "lowercase" ]
                },

我附上了包含 json 示例和 search.txt 文件的 example.js 文件来解释我的问题。我希望我的问题现在会更清楚。 这是我保存两个文件的onedrive的链接。 https://1drv.ms/f/s!AsW4Pb3Y55Qjb34OtQI7qQotLzc

【问题讨论】:

    标签: elasticsearch elasticsearch-2.0


    【解决方案1】:

    您使用 ngram 有什么特别的原因吗? Elasticsearch 在“查询”以及您索引的文本上使用相同的分析器 - 除非明确指定 search_analyzer,正如@Adam 在他的回答中提到的那样。在您的情况下,使用带有小写过滤器的standard tokenizer 可能就足够了

    我使用以下设置和映射创建了一个索引:

    {
       "settings": {
          "analysis": {
             "analyzer": {
                "custom_analyzer": {
                   "type": "custom",
                   "tokenizer": "standard",
                   "filter": [
                      "lowercase"
                   ]
                }
             }
          }
       },
       "mappings": {
          "typehere": {
             "properties": {
                "name": {
                   "type": "string",
                   "analyzer": "custom_analyzer"
                },
                "description": {
                   "type": "string",
                   "analyzer": "custom_analyzer"
                }
             }
          }
       }
    }
    

    索引两个文档 文件 1

    PUT /test_index/test_mapping/1
        {
            "name" : "Sara Connor",
            "Description" : "My real name is Sarah Connor."
        }
    

    文件 2

    PUT /test_index/test_mapping/2
        {
            "name" : "John Connor",
            "Description" : "I might save humanity someday."
        }
    

    做一个简单的搜索

    POST /test_index/_search?query=sara
    {
        "query" : {
            "match" : {
                "name" : "SARA"
            }
        }
    }
    

    并且只取回第一个文档。我也尝试了“sara”和“Sara”,结果相同。

    {
      "took": 12,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 1,
        "max_score": 0.19178301,
        "hits": [
          {
            "_index": "test_index",
            "_type": "test_mapping",
            "_id": "1",
            "_score": 0.19178301,
            "_source": {
              "name": "Sara Connor",
              "Description": "My real name is Sarah Connor."
            }
          }
        ]
      }
    }
    

    【讨论】:

    • 用 sara 可以搜索,但是当它涉及到 Sara 或 SARA 时,它什么也没有显示,这就是我真正为大写而苦苦挣扎的地方。
    • 我忘了提到我正在使用带有弹性搜索的“头插件”,所以我首先进行映射,然后将数据上传到弹性搜索,然后执行搜索。
    • @jay 我考虑过标准分析器,但 zeeshankhan 指定了关键字分析器......也许他的关键字分析器有问题,因为该分析器将输入字符串中的所有内容放入令牌中。 zeeshankhan 给我们一个示例 json 和搜索输入字符串,并告诉我们你想要得到什么结果。如果您提供此内容,我将为您创建要点。
    • @jay 我今天将提供一个示例,那么也许我的问题更清楚,并且有一些解决方案。我真的很感谢大家对我的帮助。
    • 我添加了 example.js 并在 search.txt 中添加了我的搜索输入字符串问题,意思是我想要的搜索结果。
    【解决方案2】:

    对全文搜索字段(已分析)执行两次分析过程:第一次是存储数据时,第二次是搜索时。值得一提的是,输入 JSON 将以与搜索查询的输出相同的形式返回。分析过程仅用于为倒排索引创建标记。您的解决方案的关键是以下步骤:

    1. 创建两个分析器,一个使用 ngram 过滤器,第二个分析器 没有 ngram 过滤器,因为您不需要分析输入搜索 使用 ngram 进行查询,因为您有一个要搜索的确切值。
    2. 为您的字段正确定义映射。里面有两个字段 允许您指定分析器的映射。一个用于 存储(分析器)和第二个,用于搜索 (search_analyzer) – 如果您只指定了分析器字段,那么 指定的分析器用于索引和搜索时间。

    您可以在此处阅读有关它的更多信息: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-analyzer.html

    你的代码应该是这样的:

    PUT /my_index
    {
       "settings": {
          "analysis": {
             "filter": {
                "ngram_filter": {
                   "type": "ngram",
                   "min_gram": 1,
                   "max_gram": 5
                }
             },
             "analyzer": {
                "index_store_ngram": {
                   "type": "custom",
                   "tokenizer": "standard",
                   "filter": [
                      "ngram_filter",
                      "lowercase"
                   ]
                }
             }
          }
       },
       "mappings": {
          "my_type": {
             "properties": {
                "name": {
                   "type": "string",
                   "analyzer": "index_store_ngram",
                   "search_analyzer": "standard"
                }
             }
          }
       }
    }
    
    post /my_index/my_type/1
    {
         "name": "Sara_11_01"
    }
    
    GET /my_index/my_type/_search
    {
        "query": {
            "match": {
               "name": "sara"
            }
        }
    }
    
    GET /my_index/my_type/_search
    {
        "query": {
            "match": {
               "name": "SARA"
            }
        }
    }
    
    GET /my_index/my_type/_search
    {
        "query": {
            "match": {
               "name": "SaRa"
            }
        }
    }
    

    编辑 1:更新了问题中提供的新示例的代码

    【讨论】:

    • 亚当当我把上述方法放在elasticsearch“头插件”中时。它总是给出下面提到的错误。虽然提到了 tyoe
    • "type": "illegal_argument_exception", "reason": "TokenFilter [analyzer] 必须有一个与之关联的类型"
    • 这很奇怪。我正在使用 Elasticsearch 2.3.2 和 Sense chrome 插件,一切正常。您的 Elasticsearch 版本是什么?
    • 我正在使用的弹性搜索版本为“elasticsearch-2.4.1”............上面提到的错误我已经解决了,但它仍然可以小写或大写。 .不是同时。 .我完全实现了上述内容,但仍然不能在这两种情况下工作。
    • 我添加了 example.js 和 serach.txt 文件。够了吗?。 .
    【解决方案3】:

    这个答案是在 ElasticSearch 7.14 的上下文中。所以,让我用另一种方式重新格式化这个问题的提问:

    Irrespective of the actual case type provided in the match query, you would like to be able to get those documents that have been analysed with :

       "tokenizer": "keyword",
       "filter": [ "ngram_filter", "lowercase" ]
    

    现在,进入答案部分:

    无法让match 查询返回已使用过滤器lowercase 分析的文档,并且match 查询包含大写字母。您在settings 中应用的analysis 在更新和搜索数据时均适用。尽管也可以应用不同的分析器进行更新和搜索,但我认为这对您的情况没有帮助。在进行查询之前,您必须将匹配查询值转换为小写。所以,如果你的过滤器是lowercase,你不能说matchSara或SARA或sAra等。match参数应该全部小写,就像在你的分析器中一样。

    【讨论】:

      猜你喜欢
      • 2019-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 2016-08-03
      • 2010-12-29
      • 1970-01-01
      相关资源
      最近更新 更多