webentwicklung-frage-antwort-db.com.de

elasticsearch bool query muss mit kombiniert werden OR

Ich versuche gerade, eine Solr-basierte Anwendung auf Elasticsearch zu migrieren.

Ich habe diese Lucene-Abfrage

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)

Soweit ich es verstehe, ist dies eine Kombination von MUST-Klauseln in Kombination mit booleschem ODER: 

"Holen Sie sich alle Dokumente, die (foo AND bar im Namen) enthalten OR (foo AND bar in info). Danach filtern Sie die Ergebnisse nach Bedingungsstatus = 1 und laden Sie Dokumente mit einem Bild auf."

Ich habe versucht, eine bool-Abfrage mit MUST zu verwenden, aber ich schaffe es nicht, boolean OR in must-Klauseln zu bekommen. Folgendes habe ich:

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

Wie Sie sehen, fehlen MUST-Bedingungen für "Info".

Hat jemand eine Lösung?

Ich danke dir sehr.

** UPDATE **

Ich habe meine Elasticsearch-Abfrage aktualisiert und diese Funktionsbewertung entfernt. Mein Grundproblem besteht immer noch.

96
Jesse

Es ist mir schließlich gelungen, eine Abfrage zu erstellen, die genau das tut, was ich wollte:

Eine gefilterte verschachtelte boolesche Abfrage ... Ich bin nicht sicher, warum dies nicht dokumentiert ist. Vielleicht kann mir hier jemand sagen?

Hier ist die Abfrage:

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

In Pseudo-SQL:

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

Bitte beachten Sie, dass es abhängig von Ihrer Dokumentfeldanalyse und den Zuordnungen ist, wie name = foo intern behandelt wird. Dies kann von unscharfem bis zu striktem Verhalten variieren.

"minimum_should_match": 1 besagt, dass mindestens eine der sollte -Anweisungen wahr sein muss.

Diese Anweisung bedeutet, dass immer dann, wenn sich in der Ergebnismenge ein Dokument befindet, das has_image: 1 enthält, dieses um den Faktor 100 angehoben wird. Dies ändert die Reihenfolge der Ergebnisse.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]

Habt Spaß Jungs :)

53
Jesse
  • ODERwird buchstabiert sollte
  • UNDwird geschrieben muss
  • NOCHwird geschrieben should_not

Beispiel:

Sie möchten alle Elemente anzeigen, die (rundes AND (rotes OR blau)) sind:

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

Sie können auch komplexere Versionen von OR ausführen. Wenn Sie beispielsweise mindestens 3 von 5 übereinstimmen möchten, können Sie unter "soll" 5 Optionen angeben und eine "minimum_should" von 3 festlegen.

Vielen Dank an Glen Thompson und Sebastialonso, dass Sie herausgefunden haben, wo meine Schachtelung vorher nicht richtig war.

Danke auch an Fatmajk für den Hinweis, dass "Begriff" in "ElasticSearch 6" zu "übereinstimmen" wird.

229
Daniel Fackrell

Mit dem oben genannten bekomme ich 

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

Das hat bei mir funktioniert

Für Elasticsearch 5.6.4 + aktualisiert

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

ElasticSearch ist definitiv schrecklich, wenn es um einfache Abfragen wie AND, OR oder IN geht. Sie können jedoch auf intelligente Weise Ihre Abfrage als SQL schreiben und dann mit diesem hervorragenden Online-Tool in die ElasticSearch-Syntax konvertieren:

SQL in ElasticSearch-Konverter

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

Sie können mir später danken :)

10
Sliq

Ich musste dieses Problem vor kurzem auch lösen, und nach einer ganzen Reihe von Versuchen und Fehlern kam ich dazu (in PHP, aber direkt auf das 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]]
        ]
    ]
]

Welches ist in SQL so ähnlich:

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>

Der Schlüssel bei all dem ist die Einstellung minimum_should_match. Andernfalls überschreibt die filter die should vollständig. 

Hoffe das hilft jemandem!

2
Benjamin Dowson

Auf diese Weise können Sie mit Kibana mehrere Bool-Abfragen in einer äußeren Bool-Abfrage verschachteln.

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" : {} 
                                 }     
                               ]
                          }
                 }
             ]
        }
    }
}

So können Sie eine Abfrage in ES verschachteln Es gibt weitere Typen in "bool" wie - 1. Filter 2. must_not

1
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

In must müssen Sie das Abfragebedingungsfeld hinzufügen, mit dem Sie mit AND arbeiten möchten, und in should müssen Sie die Abfragebedingung hinzufügen, die Sie mit OR bearbeiten möchten.

Sie können dies überprüfen: https://github.com/Smile-SA/elasticsuite/issues/972

0
alakh kumar