gpt4 book ai didi

elasticsearch - 如何匹配多个单词作为标记前缀

转载 作者:行者123 更新时间:2023-12-04 06:19:18 26 4
gpt4 key购买 nike

我想接受像“jan do”这样的查询,并让它匹配像“jane doe”、“don janek”这样的值——当然还有:“jan do”、“do jan”。

所以目前我能想到的规则是:

  • 基于非字母数字值(例如空格、符号、标点符号)对查询进行标记化
  • 每个查询标记充当数据存储中匹配标记的前缀
  • token 出现的顺序无关紧要。更喜欢“jan do”而不是“do jan”会很好

  • 到目前为止,我有这个映射
    PUT /test
    {
    "settings": {
    "analysis": {
    "analyzer": {
    "my_keyword": {
    "type": "custom",
    "tokenizer": "keyword",
    "filter": [
    "asciifolding",
    "lowercase"
    ]
    }
    }
    }
    },
    "mappings": {
    "question": {
    "properties": {
    "title": {
    "type": "string"
    },
    "answer": {
    "type": "object",
    "properties": {
    "text": {
    "type": "string",
    "analyzer": "my_keyword",
    "fields": {
    "stemmed": {
    "type": "string",
    "analyzer": "standard"
    }
    }
    }
    }
    }
    }
    }
    }
    }

    我一直在搜索词组:
    POST /test/_search
    {
    "query": {
    "dis_max": {
    "tie_breaker": 0.7,
    "boost": 1.2,
    "queries": [
    {
    "match": {
    "answer.text": {
    "query": "jan do",
    "type": "phrase_prefix"
    }
    }
    },
    {
    "match": {
    "answer.text.stemmed": {
    "query": "jan do",
    "operator": "and"
    }
    }
    }
    ]
    }
    }
    }

    当事情真正开始该短语时,这可以正常工作,但现在我想标记查询并将每个标记视为前缀。

    有没有办法做到这一点(可能在查询时)?

    我的另一个选择是构建一个这样的查询:
    POST test/_search
    {
    "query": {
    "bool": {
    "should": [
    {
    "prefix": {
    "answer.text.stemmed": "jan"
    }
    },
    {
    "prefix": {
    "answer.text.stemmed": "do"
    }
    }
    ]
    }
    }
    }

    这似乎有效,但它不保留单词的顺序。此外,我觉得那是作弊,可能不是最高效的选择。如果有 10 个前缀呢? 100?我想知道是否有人有不同的感觉。

    最佳答案

    正如上面的评论所暗示的,你应该看看 ngrams在 Elasticsearch 中,尤其是 edge ngrams .

    我在 this blog post 中写了一篇关于使用 ngrams 的介绍。为 Qbox ,但这里有一个您可以使用的快速示例。

    这是一个应用 edge ngram token filter 的索引定义以及自定义分析器的其他几个过滤器(使用 standard tokenizer )。

    方式发生了一些变化analyzers are applied在 ES 2.0 中。但请注意,我使用的是 standard analyzer"search_analyzer" .这是因为我不希望将搜索文本标记为 ngram,我希望它直接与索引标记匹配。有关详细信息的说明,请参阅博客文章。

    无论如何,这是映射:

    PUT /test_index
    {
    "settings": {
    "analysis": {
    "analyzer": {
    "autocomplete": {
    "type": "custom",
    "tokenizer": "standard",
    "filter": [
    "standard",
    "stop",
    "kstem",
    "edgengram_filter"
    ]
    }
    },
    "filter": {
    "edgengram_filter": {
    "type": "edgeNGram",
    "min_gram": 2,
    "max_gram": 15
    }
    }
    }
    },
    "mappings": {
    "doc": {
    "properties": {
    "name": {
    "type": "string",
    "analyzer": "autocomplete",
    "search_analyzer": "standard"
    },
    "price":{
    "type": "integer"
    }
    }
    }
    }
    }

    然后我索引了几个简单的文档:
    POST /test_index/doc/_bulk
    {"index":{"_id":1}}
    {"name": "very cool shoes","price": 26}
    {"index":{"_id":2}}
    {"name": "great shampoo","price": 15}
    {"index":{"_id":3}}
    {"name": "shirt","price": 25}

    现在,以下查询将为我提供预期的自动完成结果:
    POST /test_index/_search
    {
    "query": {
    "match": {
    "name": {
    "query": "ver sh",
    "operator": "and"
    }
    }
    }
    }
    ...
    {
    "took": 4,
    "timed_out": false,
    "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
    },
    "hits": {
    "total": 1,
    "max_score": 0.2169777,
    "hits": [
    {
    "_index": "test_index",
    "_type": "doc",
    "_id": "1",
    "_score": 0.2169777,
    "_source": {
    "name": "very cool shoes",
    "price": 26
    }
    }
    ]
    }
    }

    这是我在示例中使用的所有代码:

    http://sense.qbox.io/gist/c2ba05900d0749fa3b1ba516c66431ae1a9d5e61

    关于elasticsearch - 如何匹配多个单词作为标记前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33642246/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com