Elasticsearch:“starts with”短语中的第一个单词

29

我尝试使用 Elasticsearch 实现内容的 A-Z 导航。我需要展示所有以 a、b、c 等开头的结果。

我尝试过:

"query": {
        "match_phrase_prefix" : {
        "title" : {
            "query" : "a"
        }
      }
    }

上述查询还可以显示字符串中以a开头的单词的结果。

例如:

"title": "Apfelpfannkuchen",

"title": "Affogato",

"title": "Kalbsschnitzel an Aceto Balsamico",

我想仅显示第一个单词以a开头的短语。

这是我使用的映射:

$params = array(
            'index' => 'my_index',
            'body' => array(
                'settings' => array(
                    'number_of_shards' => 1,
                    'index' => array(
                        'analysis' => array(
                            'filter' => array(
                                'nGram_filter' => array(
                                    'type' => 'nGram',
                                    'min_gram' => 2,
                                    'max_gram' => 20,
                                    'token_chars' => array('letter', 'digit', 'punctuation', 'symbol')
                                )
                            ),
                            'analyzer' => array(
                                'nGram_analyzer' => array(
                                    'type' => 'custom',
                                    'tokenizer' => 'whitespace',
                                    'filter' => array('lowercase', 'asciifolding', 'nGram_filter')
                                ),
                                'whitespace_analyzer' => array(
                                    'type' => 'custom',
                                    'tokenizer' => 'whitespace',
                                    'filter' => array('lowercase', 'asciifolding')
                                ),
                                'analyzer_startswith' => array(
                                    'tokenizer' => 'keyword',
                                    'filter' => 'lowercase'
                                )
                            )
                        )
                    )
                ),
                'mappings' => array(
                    'tags' => array(
                        '_all' => array(
                            'type' => 'string',
                            'index_analyzer' => 'nGram_analyzer',
                            'search_analyzer' => 'whitespace_analyzer'
                        ),
                        'properties' => array()

                    ),
                    'posts' => array(
                        '_all' => array(
                            'index_analyzer' => 'nGram_analyzer',
                            'search_analyzer' => 'whitespace_analyzer'
                        ),
                        'properties' => array(
                            'title' => array(
                                'type' => 'string',
                                'index_analyzer' => 'analyzer_startswith',
                                'search_analyzer' => 'analyzer_startswith'
                            )
                        )
                    )
                )
            )
        );

你能分享一下映射吗? - Roopendra
这看起来像是elasticsearch2,你能标记一下吗? - Christophe Roussy
4个回答

22
如果您正在使用默认映射,则它将无法正常工作。
您需要在映射中使用关键字分词器小写过滤器
映射将为:
{
    "settings": {
        "index": {
            "analysis": {
                "analyzer": {
                    "analyzer_startswith": {
                        "tokenizer": "keyword",
                        "filter": "lowercase"
                    }
                }
            }
        }
    },
    "mappings": {
        "test_index": {
            "properties": {
                "title": {
                    "search_analyzer": "analyzer_startswith",
                    "index_analyzer": "analyzer_startswith",
                    "type": "string"
                }
            }
        }
    }
}

test_index 上的搜索查询:

{
    "query": {
        "match_phrase_prefix": {
            "title": {
                "query": "a"
            }
        }
    }
}

它将返回所有以a开头的文章标题


非常完美的工作。非常感谢你! - alin
我遇到了一个问题:查询结果最多只显示59个。 - alin
我明白了:我需要使用“max_expansions”。例如:“max_expansions”:1000。 - alin
2
有没有一种方法可以在不使用match_phrase_prefixprefix的情况下实现这个功能? - advncd
我正在处理许多应用程序的结构化日志。我无法预先声明所有属性或了解它们的类型。有没有办法动态地做到这一点? - Billy Jake O'Connor

2
另外,还可以使用 span_near:
GET your_index/_search
{
  "query": {
    "span_first": {
      "match": {
        "span_term": {
          "your_field": "first_token"
        }
      },
      "end": 1
    }
  },
  "_source": "your_field"
}

0

我正在根据this gist更新@Roopendra的答案。因此,最近版本中有更新,searchindex初始化程序似乎无法工作,它们只被替换为initializers,而string需要替换为text

因此,我们有以下映射文件

{
    "settings": {
        "index": {
            "analysis": {
                "analyzer": {
                    "analyzer_startswith": {
                        "tokenizer": "keyword",
                        "filter": "lowercase"
                    }
                }
            }
        }
    },
    "mappings": {
        "test_index": {
            "properties": {
                "title": {
                    "analyzer": "analyzer_startswith",
                    "type": "text"
                }
            }
        }
    }
}

使用以下查询

{
    "query": {
        "match_phrase_prefix": {
            "title": {
                "query": "a",
                "max_expansions": 100
            }
        }
    }
}

我在查询中添加了max_expansions,因为默认值似乎是5,所以我得到了错误的结果,而在你的情况下该值可能会更高。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接