web-dev-qa-db-ja.com

elasticsearchブールクエリはORと組み合わせる必要があります

私は現在solrベースのアプリケーションをelasticsearchに移行しようとしています。

私はこのluceneクエリを持っています

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

私が理解している限りでは、これはブールORと組み合わせたMUST句の組み合わせです。

「(名前のfoo ANDバー)OR(情報のfoo ANDバー)を含むすべてのドキュメントを取得します。その後、条件状態= 1でフィルタが実行され、イメージのあるドキュメントが追加されます。

MUSTでboolクエリを使おうとしましたが、ブール値の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
            }
          }
        }
      ]
    }
  }
}

ご覧のとおり、 "info"に対するMUST条件がありません。

誰もが解決策を持っていますか?

どうもありがとうございます。

**アップデート**

私のelasticsearchクエリを更新し、その機能スコアを取り除きました。私の基本的な問題はまだ存在します。

116
Jesse

私はようやく私が欲しかったことを正確に実行するクエリを作成することに成功しました:

フィルター処理されたネストされたブール照会。これが文書化されていない理由はわかりません。たぶんここの誰かが私に言うことができる?

これがクエリです:

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

疑似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文の少なくとも1つが真でなければならないと言います。

このステートメントは、has_image:1を含む結果セットにドキュメントがある場合は常に、ファクター100でブーストされることを意味します。これにより、結果の順序が変わります。

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

お楽しみください:)

55
Jesse
  • またはの綴りはず
  • のスペル必須
  • NORのつづりがあるshould_not

例:

あなたは(丸AND(赤OR青))であるすべてのアイテムを見たいです。

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

より複雑なバージョンのORを実行することもできます。たとえば、5つのうち3つ以上に一致させる場合は、「should」の下に5つのオプションを指定し、「minimum_should」を3に設定できます。

Glen ThompsonとSebastialonsoのおかげで、私のネスティングがこれまでとはまったく異なる場所を見つけてくれてありがとう.

ElasticSearch 6で "term"が "match"になることを指摘してくれたFatmajkにも感謝します。

275
Daniel Fackrell

上記を使って私は得る

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

これは私のために働きました

Elasticsearch 5.6.4以降に更新されました

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

ElasticSearchは、AND、OR、またはINのような単純なクエリに関しては間違いなく恐ろしいものです。しかし、あなたは賢いやり方でSQLとしてクエリを書き、それからこの優れたオンラインツールでElasticSearch構文に変換することができます。

SQLからElasticSearchへのコンバータ

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

あなたは後で私に感謝することができます:)

11
Sliq

私も最近この問題も解決しなければなりませんでした、そして試行錯誤の末、私はこれを思いつきました(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設定です。これがないと、filtershouldを完全にオーバーライドします。

これが誰かに役立つことを願っています!

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

mustにはANDを操作したいクエリ条件配列を追加する必要があり、shouldにはORを操作したいクエリ条件を追加する必要があります。

あなたはこれをチェックすることができます: https://github.com/Smile-SA/elasticsuite/issues/972

0
alakh kumar

これは、Kibanaを使用して、1つの外側のboolクエリに複数のboolクエリを入れ子にする方法です。

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

これが、ESでクエリを入れ子にする方法です。「bool」には、次のような種類があります。

0