elasticsearch bool query必须与OR结合使用

Jes*_*sse 147 elasticsearch

我目前正在尝试将基于solr的应用程序迁移到elasticsearch.

我有这个lucene查询

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)
Run Code Online (Sandbox Code Playgroud)

据我所知,这是MUST子句与布尔OR组合的组合:

"获取包含(foo AND bar in name)OR(foo AND bar in info)的所有文档.之后过滤条件状态= 1,并提升具有图像的文档."

我一直试图使用一个bool查询,但我没有得到boolean OR到must子句.这是我有的:

GET /test/object/_search
{
  "from": 0,
  "size": 20,
  "sort": {
    "_score": "desc"
  },
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "foo"
          }
        },
        {
          "match": {
            "name": "bar"
          }
        }
      ],
      "must_not": [],
      "should": [
        {
          "match": {
            "has_image": {
              "query": 1,
              "boost": 100
            }
          }
        }
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,缺少"信息"的必须条件.

有没有人有办法解决吗?

非常感谢.

**更新**

我更新了我的弹性搜索查询并摆脱了该功能评分.我的基本问题仍然存在.

Dan*_*ell 339

  • 拼写应该
  • AND拼写必须
  • NOR拼写为should_not

例:

您想要查看所有项目(圆形AND(红色或蓝色)):

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {"shape": "round"}
                },
                {
                    "bool": {
                        "should": [
                            {"term": {"color": "red"}},
                            {"term": {"color": "blue"}}
                        ]
                    }
                }
            ]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以执行更复杂的OR版本,例如,如果要匹配至少3个中的3个,则可以在"should"下指定5个选项并将"minimum_should"设置为3.

感谢Glen Thompson和Sebastialonso找到我的筑巢之前不太合适的地方.

还要感谢Fatmajk指出"术语"在ElasticSearch 6中变得"匹配".

  • 为什么他们不在文档中添加这么简单的例子和​​解释!文档中的示例非常混乱. (20认同)
  • 当我尝试这个例子时,我回到了`[term]格式错误的查询,预期[END_OBJECT]但找到[FIELD_NAME]`.这是某种版本依赖吗? (18认同)
  • 6个月后,阅读所有Elastic文档,这是我第一次完全理解如何实现布尔逻辑.我认为官方文件缺乏明确性. (13认同)
  • @Amir我可以为您清理哪些错误信息?在上面显示的上下文中,默认的“ minimum_should”为1,如果将至少一项匹配,则将其包装在“ bool”中将导致该组为true,否则为false。创建此答案的动机是,我正在解决此类问题,而在此类站点上可以找到的可用文档甚至答案充其量也无济于事,因此我一直在进行研究,直到我对扎实的扎实了解为止发生了什么。我很高兴欢迎任何关于如何进一步改善答案的建议。 (3认同)
  • 将`should`拉入上层`bool`,包括`minimum_should_match:1`工作? (2认同)
  • @DanielFackrell请修复缺少大括号的`should`值 (2认同)
  • @DanneJ显然,您需要在单个对象中包含"shape":"round"元素,并在兄弟对象中包含内部"bool"部分.这是有效的,但似乎它不是同一个查询. (2认同)
  • 这是错误的,应该与OR不同! (2认同)

Jes*_*sse 60

我终于设法创建了一个完全符合我想要的查询:

过滤的嵌套布尔查询.我不确定为什么没有记录.也许有人可以告诉我?

这是查询:

GET /test/object/_search
{
  "from": 0,
  "size": 20,
  "sort": {
    "_score": "desc"
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "state": 1
              }
            }
          ]
        }
      },
      "query": {
        "bool": {
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "name": "foo"
                    }
                  },
                  {
                    "match": {
                      "name": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "info": "foo"
                    }
                  },
                  {
                    "match": {
                      "info": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            }
          ],
          "minimum_should_match": 1
        }
      }    
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在伪SQL中:

SELECT * FROM /test/object
WHERE 
    ((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1
Run Code Online (Sandbox Code Playgroud)

请记住,这取决于您的文档字段分析和映射如何在内部处理name = foo.这可以从模糊到严格的行为变化.

"minimum_should_match":1表示,至少有一个should语句必须为true.

这个语句意味着只要结果集中有一个包含has_image:1的文档,它就会被因子100提升.这会改变结果排序.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]
Run Code Online (Sandbox Code Playgroud)

有乐趣的人:)

  • 哇靠.有没有人有更好的解决方案?感谢发布这个,但这绝对是在查询中实现逻辑OR的过于复杂. (20认同)
  • @EricAlford 2015年的答案基于早期版本的ES.随意提供更好的解决方案. (4认同)
  • 此查询不仅不必要很长,而且使用不推荐的语法.@ daniel-fackrell答案应该是公认的答案. (2认同)
  • 想法:接管/分叉 ElasticSearch,以用户友好的方式重写它,为其添加简单的查询语言,获胜!我们只需要资金。算我一个!还有谁 ? (2认同)
  • 伪 SQL 看起来不正确:“(name=foo AND name=bar)”总是“False”,“(info=foo AND info=bar)”也是。所以 WHERE 条件总是“False” (2认同)

Ben*_*son 7

我最近也不得不解决这个问题,经过大量的反复试验,我想出了这个(在 PHP 中,但直接映射到 DSL):

'query' => [
    'bool' => [
        'should' => [
            ['prefix' => ['name_first' => $query]],
            ['prefix' => ['name_last' => $query]],
            ['prefix' => ['phone' => $query]],
            ['prefix' => ['email' => $query]],
            [
                'multi_match' => [
                    'query' => $query,
                    'type' => 'cross_fields',
                    'operator' => 'and',
                    'fields' => ['name_first', 'name_last']
                ]
            ]
        ],
        'minimum_should_match' => 1,
        'filter' => [
            ['term' => ['state' => 'active']],
            ['term' => ['company_id' => $companyId]]
        ]
    ]
]
Run Code Online (Sandbox Code Playgroud)

它映射到 SQL 中的类似内容:

SELECT * from <index> 
WHERE (
    name_first LIKE '<query>%' OR
    name_last LIKE '<query>%' OR
    phone LIKE  '<query>%' OR
    email LIKE '<query>%'
)
AND state = 'active'
AND company_id = <query>
Run Code Online (Sandbox Code Playgroud)

这一切的关键是minimum_should_match设置。没有这个,将filter完全覆盖should.

希望这可以帮助某人!


nir*_*ale 5

这样,您可以使用Kibana在多个外部布尔查询中嵌套多个布尔查询,

布尔值表示我们正在使用布尔值

必须AND

应该

GET my_inedx/my_type/_search
{
    "query" : {
       "bool": {             //bool indicates we are using boolean operator
            "must" : [       //must is for **AND**
                 {
                   "match" : {
                         "description" : "some text"  
                     }
                 },
                 {
                    "match" :{
                          "type" : "some Type"
                     }
                 },
                 {
                    "bool" : {          //here its a nested boolean query
                          "should" : [  //should is for **OR**
                                 {
                                   "match" : {
                                       //ur query
                                  }
                                 },
                                 { 
                                    "match" : {} 
                                 }     
                               ]
                          }
                 }
             ]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是在ES中嵌套查询的方式

“布尔”中有更多类型,例如-

  1. 过滤

  2. 一定不


小智 5

如果您使用的是 Solr 的默认或 Lucene 查询解析器,您几乎总是可以将其放入查询字符串查询中:

POST test/_search
{
  "query": {
    "query_string": {
      "query": "(( name:(+foo +bar) OR info:(+foo +bar)  )) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

也就是说,您可能想要使用布尔查询,例如您已经发布的查询,或者甚至是两者的组合。