pesquisa elastica bool query combine must com ou

Estou a tentar migrar uma aplicação baseada em solr para a pesquisa elastica.

tenho esta pergunta lucene

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)
Tanto quanto sei, trata-se de uma combinação de cláusulas obrigatórias combinadas com cláusulas booleanas ou:

"obter todos os documentos que contenham (foo e bar em nome) ou (foo e bar em informação). Depois que o filtro resulta por estado de condição=1 e impulsionar documentos que têm uma imagem."

eu tenho tentado usar uma consulta bool com MUST mas eu estou falhando em obter boolean ou em must clauses. Eis o que tenho:

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
            }
          }
        }
      ]
    }
  }
}

Como pode ver, faltam as condições necessárias para" info".

Alguém tem uma solução?

Muito obrigado.

** Actualizar * *

actualizei a minha pesquisa elastica e livrei-me desse resultado de funções. O meu problema básico ainda existe.

Author: Jesse, 2015-02-16

6 answers

  • ou escreve-se"deve"
  • e escreve-se"must"
  • nem se escreve "should_not"

Exemplo:

Você quer ver todos os itens que são (redondos e (vermelho ou azul)):

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {"shape": "round"},
                },
                {
                    "bool": {
                        "should": [
                            {"term": {"color": "red"}},
                            {"term": {"color": "blue"}}
                        ]
                    }
                }
            ]
        }
    }
}

Você também pode fazer versões mais complexas de ou, por exemplo, se quiser corresponder pelo menos 3 em 5, você pode especificar 5 opções em "DEVE" e definir um "minimum_ should" de 3.

Obrigado ao Glen Thompson e ao Sebastialonso por descobrirem onde é o meu ninho. não estava certo antes.

Obrigado também ao Fatmajk por apontar que "termo" se torna "compatível" na ElasticSearch 6.

 152
Author: Daniel Fackrell, 2018-09-06 04:21:43
Finalmente consegui criar uma consulta que faz exactamente o que eu queria ter.

Uma pesquisa booleana filtrada. Não sei por que razão isto não está documentado. Talvez alguém aqui me possa dizer?

Aqui está a Pergunta:

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
        }
      }    
    }
  }
}

Em pseudo-SQL:

SELECT * FROM /test/object
WHERE 
    ((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1

Por favor, tenha em mente que depende da sua análise de campo do documento e mapeamentos como o nome=foo é tratado internamente. Isto pode variar de um comportamento difuso a estrito.

"minimum_ should_ match": 1 diz, que pelo menos uma das declarações deve ser verdade.

Estas declarações significam que sempre que existe um documento no conjunto de resultados que contém has_image:1 é reforçado pelo factor 100. Isto muda a ordenação do resultado.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]
Divirtam-se.
 46
Author: Jesse, 2015-02-16 14:22:24

Usando o acima eu fico

[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]

Isto funcionou comigo.

Actualizado para a pesquisa elastica 5. 6. 4 +

{
    "query": {
        "bool": {
            "must": [
                {"term": {"shape": "round"}},
                {"bool": {
                    "should": [
                        {"term": {"color": "red"}},
                        {"term": {"color": "blue"}}
                    ]
                }}
            ]
        }
    }
}
 17
Author: Glen Thompson, 2018-03-10 20:40:01

Recentemente eu tive que resolver este problema também, e depois de um monte de tentativa e erro eu cheguei com isso (em PHP, mas mapeia diretamente para o 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]]
        ]
    ]
]

Que mapeia para algo como isto em 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>

A chave em tudo isto é a configuração minimum_should_match. Sem isto, o filter sobrepõe-se totalmente ao should.

Espero que isto ajude alguém!
 2
Author: Benjamin Dowson, 2016-11-04 15:20:04
A busca elastica é definitivamente horrível quando se trata de perguntas simples como, ou dentro. Mas, você pode ir pela maneira inteligente e escrever sua consulta como SQL e depois convertê - la para a sintaxe ElasticSearch com esta excelente ferramenta online:

Conversor de SQL para ElasticSearch

Https://www.toolsbuzz.com/query-converter

Podes agradecer-me mais tarde.
 1
Author: Sliq, 2018-08-10 20:34:26
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

Em must tem de adicionar a lista de condições da consulta com a qual deseja trabalhar AND e em should tem de adicionar a condição da pesquisa com a qual deseja trabalhar OR.

Podes verificar isto: https://github.com/Smile-SA/elasticsuite/issues/972

 0
Author: alakh kumar, 2018-06-26 06:13:12