我目前正在尝试将一个基于solr的应用程序迁移到elasticsearch。
我有这个lucene查询:
((
name:(+foo +bar)
OR info:(+foo +bar)
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)
据我所知,这是一个must子句与布尔OR的组合:
获取所有包含(foo AND bar in name)或(foo AND bar in info)的文档。之后,根据条件state=1过滤结果,并增强具有图像的文档。
我一直试图使用bool查询必须,但我未能得到布尔或必须子句。以下是我所拥有的:
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
}
}
}
]
}
}
}
如你所见,info的must条件缺失了。
**更新**
我已经更新了我的elasticsearch查询,并摆脱了该函数得分。我的基本问题仍然存在。
我终于设法创建了一个查询,它确实是我想要的:
筛选的嵌套布尔查询。
我不确定为什么这没有被记录下来。也许有人能告诉我?
下面是查询:
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
}
}
}
}
}
在pseudo-SQL:
SELECT * FROM /test/object
WHERE
((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1
请记住,name=foo在内部是如何处理的,这取决于您的文档字段分析和映射。这可以从模糊的行为到严格的行为。
"minimum_should_match": 1表示,至少有一个should语句必须为真。
这句话意味着只要结果集中有一个包含has_image:1的文档,它就会被提升100倍。这改变了结果排序。
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
祝你们玩得开心!
我最近也不得不解决这个问题,经过大量的试验和错误后,我想出了这个(在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]]
]
]
]
在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>
所有这些的关键是minimum_should_match设置。没有这个过滤器完全覆盖应该。
希望这能帮助到一些人!
OR的拼写是should
AND的拼写是must
NOR的拼写是should_not
例子:
你想看到所有的项目(圆形和(红色或蓝色)):
{
"query": {
"bool": {
"must": [
{
"term": {"shape": "round"}
},
{
"bool": {
"should": [
{"term": {"color": "red"}},
{"term": {"color": "blue"}}
]
}
}
]
}
}
}
您还可以执行更复杂的OR版本,例如,如果您想匹配5个中的至少3个,您可以在“should”下指定5个选项,并将“minimum_should”设置为3。
感谢格伦·汤普森和塞巴斯蒂安·阿隆索,他们找到了我以前筑巢不太合适的地方。
还要感谢Fatmajk指出,在ElasticSearch Version 6中,“term”变成了“match”。