【问题标题】:Partial word search - ElasticSearch 1.7.2部分词搜索 - ElasticSearch 1.7.2
【发布时间】:2016-01-07 08:30:08
【问题描述】:

我一直在尝试使用 ElasticSearch 为应用程序构建搜索模块。下面是我从其他 StackOverflow 帖子中阅读的示例代码构建的索引结构。

{
  "megacorp4":{
    "settings":{
      "analysis":{
        "analyzer":{
          "my_analyzer":{
            "type":"custom",
            "tokenizer":"my_ngram_tokenizer",
            "filter":[
              "my_ngram_filter"
            ]
          }
        },
        "filter":{
          "my_ngram_filter":{
            "type":"edgeNGram",
            "min_gram":3,
            "max_gram":15
          }
        },
        "tokenizer":{
          "my_ngram_tokenizer":{
            "type":"edgeNGram",
            "min_gram":3,
            "max_gram":15
          }
        }
      },
      "mappings":{
        "employee":{
          "properties":{
            "about":{
              "type":"string",
              "analyzer":"my_analyzer"
            },
            "age":{
              "type":"long"
            },
            "first_name":{
              "type":"string"
            },
            "interests":{
              "type":"string",
              "analyzer":"my_analyzer"
            },
            "last_name":{
              "type":"string"
            }
          }
        }
      }
    }
  }
}

以下是我插入的用于测试搜索功能的记录

[
  {
    "first_name":"John",
    "last_name":"Smith",
    "age":25,
    "about":"I love to go rock climbing",
    "interests":[
      "sports",
      "music"
    ]
  },
  {
    "first_name":"Douglas",
    "last_name":"Fir",
    "age":35,
    "about":"I like to build album climb cabinets",
    "interests":[
      "forestry",
      "music"
    ]
  },
  {
    "first_name":"Jane",
    "last_name":"Smith",
    "age":32,
    "about":"I like to collect rock albums",
    "interests":[
      "music"
    ]
  }
]

我使用 API(通过 POSTMAN)和 Python 客户端对“关于”列进行了搜索,如下所示:

API 查询:

localhost:9200/megacorp4/_search?q=climb

Python 查询:

from elasticsearch import Elasticsearch
from pprint import pprint
es = Elasticsearch()
res = es.search(index="megacorp4", body={"query": {"match": {'about':"climb"}}})
pprint(res)

我只能获得完全匹配,并且在输出中没有得到带有“爬升”的结果。但是,当我在查询中将 'climb' 替换为 'climb*' 时,我得到 2 条记录为 'climb' 和 'climbing'。我不想使用 '*' 通配符方法。

我也尝试过使用“english”、“standard”和“ngram”内置分析器,但似乎没有任何效果。

需要帮助来实现在全文中将关键字搜索为部分单词。

提前致谢。

【问题讨论】:

    标签: elasticsearch full-text-search


    【解决方案1】:

    改用这个映射:

    删除测试

    PUT /test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "type": "custom",
              "tokenizer": "standard",
              "filter": [
                "my_ngram_filter"
              ]
            }
          },
          "filter": {
            "my_ngram_filter": {
              "type": "edgeNGram",
              "min_gram": 3,
              "max_gram": 15
            }
          }
        }
      },
      "mappings": {
        "employee": {
          "properties": {
            "about": {
              "type": "string",
              "analyzer": "my_analyzer"
            },
            "age": {
              "type": "long"
            },
            "first_name": {
              "type": "string"
            },
            "interests": {
              "type": "string",
              "analyzer": "my_analyzer"
            },
            "last_name": {
              "type": "string"
            }
          }
        }
      }
    }
    
    POST /test/employee/_bulk
    {"index":{}}
    {"first_name":"John","last_name":"Smith","age":25,"about":"I love to go rock climbing","interests":["sports","music"]}
    {"index":{}}
    {"first_name":"Douglas","last_name":"Fir","age":35,"about":"I like to build album climb cabinets","interests":["forestry","music"]}
    {"index":{}}
    {"first_name":"Jane","last_name":"Smith","age":32,"about":"I like to collect rock albums","interests":["music"]}
    
    GET /test/_search?q=about:climb
    
    GET /test/_search
    {
      "query": {
        "query_string": {
          "query": "about:climb"
        }
      }
    }
    
    GET /test/_search
    {
      "query": {
        "match": {
          "about": "climb"
        }
      }
    }
    

    两个变化:

    • settings 部分需要另一个右大括号
    • 用另一个替换您的自定义分词器(这对您没有帮助,因为您已经拥有 edgeNGram 过滤器),我的建议是standard分词器

    对于?q=climb 部分,默认情况下会搜索_all 字段,该字段使用standard 分析器而不是您的自定义分析器进行分析。

    所以,正确的查询是localhost:9200/megacorp4/_search?q=about:climb

    【讨论】:

    • 使用您提供的映射,插入相同的 3 条记录,并在 POSTMAN 和 Python 客户端中运行相同的搜索查询,仅获取带有 'climb' 的记录,仍然没有得到 'climbing' 记录: (
    • 试过localhost:9200/megacorp4/_search?q=about:climb,只得到climb结果而不是climbing结果..
    • 你删除了索引吗?
    • 我已经用完整的测试代码更新了我的答案:索引、映射、设置、测试数据、测试查询。
    • 是的,我使用 Python 客户端删除了索引,然后使用您提供的映射重新创建它 es.indices.delete(index='megacorp4', ignore=[400, 404])
    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2011-09-21
    • 1970-01-01
    • 2016-05-23
    相关资源
    最近更新 更多