当前位置: 首页 > 知识库问答 >
问题:

elasticsearch - match_phrase_prefix如何在term条件的基础上再进行搜索?

董霖
2024-07-30

ES版本 7.17.3

GET v2-vmail-inbox-local-000001/_search?routing=1111
{
  "sort": [
    {
      "receive_time": {
        "order": "desc"
      }
    }
  ], 
  "profile": true, 
  "size": 50, 
  "_source": ["mail_subject"], 
  "query":{
    "bool": {
      "filter": [
        {"term": {
          "receiver_code": "1111"
        }},
        {
          
          "multi_match": {
            "query": "df33",
            "type": "phrase_prefix", 
            "fields": ["sender_name","mail_subject"]
          }}
      ]
    }
  }
}

当我使用这样的DSL时,我无法搜到 阅读通知:DF33760BF_X4这样的数据
但我使用df337这种语句就可以搜到
我用profile发现term和multi_match并没有特别的先后关系,导致multi_match查询的前50个term没有命中到DF33760BF_X4这种数据
有没有什么办法能先满足term条件,在term条件满足的数据上在进行multi_match的匹配,从而避免max_expansions默认50 匹配不到数据的问题

样例数据可参考

POST v2-vmail-inbox-local-000001/_doc/1111-125830ed339e4e49ad5ffa84d7ee6d08?routing=1111
{
          "receiver_code" : "1111",
          "mail_subject" : "阅读通知:DF33760BF_X4",
          "receive_time" : 1651802115000,
          "sender_name" : "test",
          "mail_code" : "125830ed339e4e49ad5ffa84d7ee6d08",
          "sender_code" : "2222",
          "receiver_name" : "测试用户"
        }

共有1个答案

秦凯旋
2024-07-30

在Elasticsearch中,multi_match 查询的 phrase_prefix 类型确实存在一些限制,尤其是当前缀长度较长或者数据分布不均时。phrase_prefix 类型会尝试将查询词作为前缀来匹配字段中的短语,但默认情况下,它只会展开查询以匹配最多50个可能的短语。

为了解决你的问题,你可以考虑以下几种方法:

1. 使用 match_phrase_prefix 替代 multi_match

由于你只关心在特定字段上进行短语前缀查询,你可以将 multi_match 替换为 match_phrase_prefix,并指定字段。这可以使得查询更明确,并可能有助于性能。

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "receiver_code": "1111"
          }
        },
        {
          "match_phrase_prefix": {
            "mail_subject": "df33"
          }
        },
        {
          "match_phrase_prefix": {
            "sender_name": "df33"
          }
        }
      ]
    }
  }
}

注意:这种方式会分别对每个字段进行短语前缀查询,可能不是最优的,因为它不会同时考虑两个字段的相关性。

2. 调整 max_expansions

如果你确实需要使用 multi_match 并且希望扩展更多的短语,可以调整 max_expansions 的值。但是,这可能会导致查询性能下降,因为需要处理更多的匹配项。

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "receiver_code": "1111"
          }
        },
        {
          "multi_match": {
            "query": "df33",
            "type": "phrase_prefix",
            "fields": ["sender_name", "mail_subject"],
            "max_expansions": 100  // 或者更高的值
          }
        }
      ]
    }
  }
}

3. 重新考虑数据模型和索引策略

如果上述方法仍然不能解决问题,可能需要重新考虑你的数据模型和索引策略。例如,你可以考虑:

  • 使用更合适的分析器来索引 sender_namemail_subject 字段,以确保它们以适合短语前缀查询的方式被分词。
  • 引入额外的字段或使用N-gram分词器来索引这些字段,以便更灵活地处理前缀查询。

4. 分析和调试

使用Elasticsearch的Profile API来分析和调试查询,看看哪些部分最耗时或最可能未命中数据。这可以帮助你更精确地调整查询和索引策略。

结论

通常,调整 max_expansions 或更改查询类型(如使用 match_phrase_prefix)是处理短语前缀查询中常见问题的有效方法。但是,具体解决方案将取决于你的具体数据和查询需求。

 类似资料:
  • 我正在使用Nest连接到ElasticSearch并执行一些查询。到目前为止,在给定一个通配符查询的情况下,我能够得到我想要的结果,如下所示: 但是现在我需要为某个用例的查询添加附加条件。 我需要的不仅是通过查询,还需要其他两个匹配的字段: 搜索术语"*" field 1="一些字符串" field="一些指南" 我确信在弹性搜索中一定有办法做到这一点(使用Nest),但我还没有找到它。 我知道我

  • 问题内容: 我有一个类似以下设置和映射的索引; 我正在努力实现现场通配符搜索的实现。我的示例数据如下: 当我执行以下查询时; 它返回,。我认为,它仍然标记数据。它只能返回。 您能帮上忙吗? 提前致谢 问题答案: 我的解决方案历险记 如您在我的问题中所见,我已经开始审理案件。每当我更改了一部分设置后,一部分便开始工作,而另一部分则停止工作。让我给出我的解决方案历史记录: 1.) 我已将数据索引为默认

  • pre { white-space: pre-wrap; } jQuery EasyUI 插件 通过 $.fn.progressbar.defaults 重写默认的 defaults。 进度条(progressbar)提供了一种显示长时间操作进度的反馈。进度可被更新以便让用户知道当前正在执行的操作。 依赖 none 用法 创建进度条(ProgressBar) 进度条(ProgressBar)组件可

  • 问题内容: 我想使用ElasticSearch搜索文件名(而不是文件的内容)。因此,我需要找到文件名的一部分(完全匹配,没有模糊搜索)。 示例: 我有以下名称的文件: 现在,我要搜索以获取前两个文件。 搜索或应返回除最后一个文件名以外的所有文件名。 如何使用ElasticSearch做到这一点? 这是我测试过的,但始终返回零结果: 问题答案: 您粘贴的内容存在各种问题: 1)不正确的映射 创建索引

  • 如何使LDAP查询只返回所有级别中具有ou=groups的组? http://confluence.atlassian.com/display/dev/how+to+write+ldap+search+filters

  • 问题内容: 我想用UNION和limit进行查询。 我可以在mysql上解释该查询。 我在Elasticsearch上尝试过 http:// localhost:9200 / test / table / _search?pretty&source = {%22query%22:{%22dis_max%22:{%22queries%22:[{%22query%22:{%22match%22:{%2

  • 问题内容: 我有两个具有以下映射的索引(我将简化它们的映射): 1)AccountType映射: 2)ProductType映射: 现在,我有几件事需要弄清楚: 1)首先,有一个索引是一个好主意,在我的情况下是帐户,并且产品是嵌套对象,但是在这里每次我要更新/添加新产品时,我都必须重新索引(更新)整个帐户文件? 2)我的第二个问题是:我想具有搜索功能,因此,如果用户通过在文本框中键入内容进行搜索,

  • 我是ElasticSearch的新手!我有一个eShop(使用Laravel),其中包含超过1,000,000个产品,每个产品在表中都有一些属性,例如名称、描述、价格...和其他表中的一些其他属性,例如、、、、、,...这些都在单独的表中,它们将通过关系连接到产品! 所以我想有一个非常快速和可靠的搜索产品与许多过滤器!就像Android!例如,用户将能够找到具有特殊类别、标签、选项等的产品。。。!