草庐IT

ElasticSearch中minimum_should_match理解

梦想东东 2024-05-10 原文

基于elasticsearch7.6.1 和 kibana7.6.1

本文通过案例进行讲解,希望读者耐心阅读【3.查询】中的内容。

1. 创建索引

PUT goods
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

 说明:

  1. 通常情况下,为了提升搜索的效果,ik_max_word和ik_smart两种分词器需要配合使用。
  2. 即构建索引时用ik_max_word,尽可能多的分词,而搜索时用ik_smart,尽可能提高匹配准度,让用户的搜索尽可能准确。

2. 通过_bulk批量导入数据

POST goods/_bulk
{"index":{"_id":1}}
{"title":"法国原瓶进口红酒"}
{"index":{"_id":2}}
{"title":"圣罗兰山茶色口红"}
{"index":{"_id":3}}
{"title":"康师傅红烧牛肉味方便面"}
{"index":{"_id":4}}
{"title":"康师傅芥末青柠味方便面"}
{"index":{"_id":5}}
{"title":"康师傅香辣牛肉味方便面"}
{"index":{"_id":6}}
{"title":"康师傅极致酷爽红茶"}
{"index":{"_id":7}}
{"title":"新西兰进口牛奶"}

3. 查询

# match查询
# 基于"进口" OR "红酒",进行召回。
GET goods/_search
{
  "query": {
    "match": {
      "title": "进口红酒"
    }
  }
}


GET goods/_search
{
  "query": {
    "match": {
      "title": "口红"
    }
  }
}


# 基于"康师傅" OR "红烧",进行召回。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧"
      }
    }
  }
}

# 基于"康师傅" OR "红烧",进行召回,但是必须匹配两个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧",
        "operator": "or",
        "minimum_should_match": 2
      }
    }
  }
}

# 基于"康师傅" AND "红烧",进行召回。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧",
        "operator": "and"
      }
    }
  }
}

# 基于"康师傅" OR "红烧" OR "方便面",进行召回,但是必须匹配两个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧方便面",
        "operator": "or",
        "minimum_should_match": 2
      }
    }
  }
}

# 3*75%=2.25,向下取整等于2。
# 基于"康师傅" OR "红烧" OR "方便面",进行召回,但是必须匹配两个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧方便面",
        "operator": "or",
        "minimum_should_match": "75%"
      }
    }
  }
}

# 等价写法
GET goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "title": "康师傅"
          }
        },
        {
          "term": {
            "title": "红烧"
          }
        },
        {
          "term": {
            "title": "方便面"
          }
        }
      ],
      "minimum_should_match": 2
    }
  }
}


# 3*60%=1.8,向下取整等于1。
# 基于"康师傅" OR "红烧" OR "方便面",进行召回,但是必须匹配一个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧方便面",
        "operator": "or",
        "minimum_should_match": "60%"
      }
    }
  }
}

# 等价写法
GET goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "title": "康师傅"
          }
        },
        {
          "term": {
            "title": "红烧"
          }
        },
        {
          "term": {
            "title": "方便面"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}


# 如果clauses<=3,那么全部should条件都要满足,如果clauses>3,那么需要满足全部should条件的80%。
# 5*80%=4,向下取整等于4。
# 基于"康师傅" OR "红烧" OR "牛肉" OR "味" OR "方便面",进行召回,但是必须匹配4个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧牛肉味方便面",
        "operator": "or",
        "minimum_should_match": "3<80%"
      }
    }
  }
}

# 等价写法
GET goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "title": "康师傅"
          }
        },
        {
          "term": {
            "title": "红烧"
          }
        },
        {
          "term": {
            "title": "牛肉"
          }
        },
        {
          "term": {
            "title": "味"
          }
        },
        {
          "term": {
            "title": "方便面"
          }
        }
      ],
      "minimum_should_match": 4
    }
  }
}


# 如果clauses<=3,那么全部should条件都要满足,如果clauses>3,那么需要满足全部should条件的80%。
# 基于"康师傅" OR "红烧" OR "方便面",进行召回,但是必须匹配3个词以上。
GET goods/_search
{
  "query": {
    "match": {
      "title": {
        "query": "康师傅红烧方便面",
        "operator": "or",
        "minimum_should_match": "3<80%"
      }
    }
  }
}

# 等价写法
GET goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "title": "康师傅"
          }
        },
        {
          "term": {
            "title": "红烧"
          }
        },
        {
          "term": {
            "title": "方便面"
          }
        }
      ],
      "minimum_should_match": 3
    }
  }
}

  说明:

  1. "minimum_should_match": "3<80%"含义:当should分支总数小于等于3时,则必须匹配所有的should分支,当should分支总数大于3时,则至少匹配80%的should分支,同时分支数向下取整。
  2. "minimum_should_match": "60%"含义:必须匹配should分支总数的60%,同时分支数向下取整。例如,总共有7个should分支,则7*0.6=4.2,向下取整得到4,即至少匹配4个should分支。

4. 补充,对比ik_max_word和ik_smart的分词效果

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "进口红酒"
}


GET _analyze
{
  "analyzer": "ik_smart",
  "text": "康师傅红烧"
}


GET _analyze
{
  "analyzer": "ik_smart",
  "text": "康师傅红烧方便面"
}


GET _analyze
{
  "analyzer": "ik_smart",
  "text": "康师傅红烧牛肉味方便面"
}


GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "新西兰进口牛奶"
}


GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "康师傅红烧牛肉味方便面"
}


GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "康师傅香辣牛肉味方便面"
}

有关ElasticSearch中minimum_should_match理解的更多相关文章

  1. Ruby - 如何在 Prawn 中使用不同的字体? - 2

    我有一个小的Ruby程序,我在其中使用Prawn将一些文本打印成PDF,但一小部分文本是非英文字符。(其中一些文本是中文,一些是希腊文,等等)。当我运行我的程序时,我当然会收到一条错误消息,提示您的文档包含与Windows-1252字符集不兼容的文本。(Prawn::错误::IncompatibleStringEncoding)如果您需要完整的UTF-8支持,请使用TTF字体而不是PDF的内置字体。我知道我需要使用TTF字体,但我该怎么做呢?我需要从网上安装吗?如果是这样,我应该把它保存到哪里?我知道这可能是一个愚蠢的问题,但我是Ruby和Prawn的新手。谢谢!

  2. ruby - 我如何在 Ruby 中解构一个范围? - 2

    是否可以在ruby​​中使用解构来提取范围的结束和开始?modulePriceHelperdefprice_range_human(range)"$%sto$%s"%[range.begin,range.end].map(:number_to_currency)endend我知道我可以使用数组强制作为一个非常糟糕的hack:first,*center,last=*rng"$%sto$%s"%[first,last].map(:number_to_currency)但是有没有一种语法方法可以在不实际手动创建数组的情况下获取begin和end?min,max=(1..10)会很棒。

  3. ruby-on-rails - 是否可以在部分中只放置一个 rails 表单元素? - 2

    我的应用有一个选择框供用户选择“地点”。如您所料,此选择框位于一个表单中。我还在页面上的某处执行了一个操作,该操作通过AJAX创建了一个新场所。创建新field后,我想更新field选择框以反射(reflect)这一点。我的解决方案是将选择框放在局部中,并从Controller中的创建操作中呈现局部。'venue/venue_select_box'%>局部看起来像这样:'Selectavenue'%>其中f是表单引用:问题是f在部分中未定义,所以我得到一个错误。一种解决方案是包括整个表格,但我觉得没有必要这样做,因为我没有更新整个表格。关于如何解决这个问题有什么想法吗?

  4. ruby - 如何在 ruby​​ 中使用反引号开始子进程的连续输出 - 2

    我有一个ruby​​应用程序,它使用反引号将ant作为子进程执行。这没有任何问题。当我执行putant时,ruby等待子进程ant完全完成,然后将输出打印到标准输出。如何让ruby​​连续打印子进程的输出? 最佳答案 你可以使用IO.popen。IO.popen("ant")do|output|whileline=output.getsdo#...maybeputsline?somethingmoreinteresting?endend 关于ruby-如何在ruby​​中使用反引号开始子

  5. ruby - 如何在 ruby​​ 中拆分字符串并在拆分中维护空格 - 2

    我有一个字符串:"hello\tWorld\nbla"我想把它拆分成:["hello\t","World\n","bla"]我如何在Ruby中执行此操作? 最佳答案 >>"hello\tWorld\nbla".scan/\S+\s*/=>["hello\t","World\n","bla"] 关于ruby-如何在ruby​​中拆分字符串并在拆分中维护空格,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com

  6. ruby - 如何在 Ruby 中有效地解析大文本文件 - 2

    我正在编写一个导入脚本来处理一个可能有数十万行的文件(日志文件)。使用一个非常简单的方法(如下)占用了足够的时间和内存,我觉得它随时都会耗尽我的MBP,所以我终止了这个过程。#...File.open(file,'r')do|f|f.each_linedo|line|#dostuffheretolineendend这个文件特别有642,868行:$wc-lnginx.log/code/src/myimport642868../nginx.log有谁知道处理此文件中每一行的更有效(内存/cpu)方法吗?更新上面f.each_line中的代码只是将正则表达式与该行进行匹配。如果匹配失败,我

  7. ruby - 如何在 ruby​​ 中使用 getoptlong 类? - 2

    我需要有关在Ruby中使用getoptlong类的帮助。我需要执行命令prog_name.ruby-u-i-s文件名。到目前为止,我只能使用prog_name.ruby-u文件名-i文件名-s文件名来执行它。这是我的getoptlong代码:require'getoptlong'classCommonLogparser=GetoptLong.newparser.set_options(["-h","--help",GetoptLong::NO_ARGUMENT],["-u","--url",GetoptLong::NO_ARGUMENT],["-i","--ip",GetoptLong

  8. ruby - 是否可以在 Sinatra 中重写基本 URL? - 2

    是否可以重写基本URL?例如而不是www.host.com/使用www.host.com/blah/作为一个基本的url等等:get'/'do...end适用于www.host.com/blah/我可以附加到我的所有路线'/blah/..'但任何gem等。也将无法工作。这可以在Rails中轻松完成,我也想在Sinatra中使用它。 最佳答案 我为此使用了Rack中间件rack-rewrite我对此很满意:)useRack::Rewritedorewrite%r{^/\w{2}/utils},'/utils'rewrite%r{^/\

  9. ruby-on-rails - 如何在 heroku worker 中捕获内存配额异常 - 2

    我正在使用delayed_job来处理heroku的后台作业。有时我会超出我的内存分配,我会得到这样的东西:2011-11-16T02:41:25+00:00heroku[worker.1]:错误R14(超出内存配额)2011-11-16T02:41:45+00:00heroku[worker.1]:进程运行mem=542M(106.0%)我想优雅地处理这个。有没有办法知道我什么时候会超出我的内存限制?类似于rack-timeout会很棒谢谢! 最佳答案 我想我找到了一个很好的解决方案,从Oink中窃取了一些代码。gem。特别是这个

  10. ruby - 在 ruby​​ 中,方法和函数之间有区别吗 - 2

    这个问题在这里已经有了答案:关闭11年前。PossibleDuplicate:Rubyfunctionsvsmethods我只是阅读了一些ruby​​文档,似乎以可互换的方式使用术语函数和方法,我只是想知道是否有任何区别?我正在查看的文档将其称为函数:defsaysomething()puts"Hello"endsaysomething这是一个方法:defmultiply(val1,val2)result=val1*val2putsresultend这可能是某种语义,但我想检查一下jt

随机推荐