【问题标题】:Query in Elasticsearch for retrieving strings that start with a particular word在 Elasticsearch 中查询以检索以特定单词开头的字符串
【发布时间】:2016-12-26 14:40:35
【问题描述】:

我想在 elasticsearch 中编写一个查询,这样它只会给出字符串从特定单词开始的结果,例如,如果我要搜索,我现在有一个字符串“Donald Duck”和另一个字符串“Alan Donald”使用以下查询的“唐纳德”

"query": {
     query_string: {
         query: "Donald",
         fields: ['character_name']
     }
 }

那么结果应该是“Donald Duck”而不是“Alan Donald”,因为在“Donald Duck”中它以“Donald”开头。现在谁能告诉我如何编写这样的查询,我搜索了很多帖子但没有找到任何解决方案。

编辑-1

我的映射如下所示

"settings": {
        "index": {
                "analysis": {
                    "analyzer": {
                        "simple_wildcard": {
                    "tokenizer": "whitespace",
                    "filter": ["lowercase"]
                        }
                    }
                }
            }
      },
      "mappings" : {
        "college": {
                "properties":{
                    "character_name" : { "type" : "string", "index": "analyzed", "analyzer": "simple_wildcard"}

                }
            }
}

【问题讨论】:

  • 你看过匹配词组前缀吗? elastic.co/guide/en/elasticsearch/reference/master/…
  • 搜索“Donald”(末尾有空格)有用吗?
  • 可能值得考虑如何构建数据。您应该根据您想要搜索的方式在 Elastic Search 中构建数据,在这种情况下,您可以将名字和姓氏拆分为单独的字段并仅搜索“first_name”字段。
  • 对于“Donald”,结果必须是 Donald Duck,因为“Donald Duck”以“Donald”开头。
  • @NickG 没有匹配短语前缀,如果我搜索“DONALD”,它将返回两者,但感谢您的帮助。

标签: elasticsearch


【解决方案1】:

Limit Token filter 在这种特殊情况下会很有帮助。您可以通过两种不同的方式分析 character_name 字段,一种用于标准搜索操作,另一种用于获取以特定单词开头的字符串。我像这样创建了示例索引。 only_first 仅索引字符串的第一个标记。

PUT character
{
  "settings": {
    "analysis": {
      "analyzer": {
        "character_analyzer": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "one_token_limit"
          ]
        }
      },
      "filter": {
        "one_token_limit": {
          "type": "limit",
          "max_token_count": 1
        }
      }
    }
  },
  "mappings": {
    "mytype": {
      "properties": {
        "character_name": {
          "type": "string",
          "fields": {
            "only_first": {
              "type": "string",
              "analyzer": "character_analyzer"
            }
          }
        }
      }
    }
  }
}

然后你像这样查询 only_first 字段

{
  "query": {
    "query_string": {
      "fields": ["character_name.only_first"],
      "query": "Donald"
    }
  }
}

这将为您提供所需的结果。我使用了whitespace 标记器,但如果你想匹配“唐纳德-唐纳鸭”,你也可以使用标准标记器。

另一种方法是span first query,但问题是它是term query,所以'donald'会匹配但'Donald'不会匹配

{
    "span_first" : {
        "match" : {
            "span_term" : { "character_name" : "donald" }
        },
        "end" : 1
    }
}

但是“Donald”会给你零结果(区分大小写),但第一种方法肯定行得通。

编辑 1:前缀匹配

您可以像这样首先将前缀查询包装在 span 中

{
  "query": {
    "span_first": {
      "match": {
        "span_multi": {
          "match": {
            "prefix": {
              "character_name": {
                "value": "don"
              }
            }
          }
        }
      },
      "end": 1
    }
  }
}

请勿在查询中使用 "*"

希望对你有帮助!

【讨论】:

  • 非常感谢,span_first 查询对我来说工作正常,只剩下一件事如何将 span_first 查询与其中的通配符查询而不是匹配查询结合起来,因为我想搜索“Donal *” 也为此我的 es 应该返回“唐老鸭”。
  • 我已经编辑了我的答案。我不确定您为什么不使用“限制令牌”方法,因为跨度查询区分大小写。您必须 100% 确定它不会在将来造成任何问题。 character_name 字段的映射是什么?
  • 你可以查看我编辑的帖子,我已经更新了我的映射,因为我正在小写我的所有标记,所以我认为区分大小写不会是一个问题。
  • 非常感谢人前缀匹配查询就像一个魅力,感谢你帮助我离开这里。
  • 很高兴我能帮上忙
猜你喜欢
  • 1970-01-01
  • 2022-11-17
  • 2018-12-22
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 2019-11-03
  • 2020-12-12
  • 1970-01-01
相关资源
最近更新 更多