gabungan permintaan kueri elasticsearch harus dengan OR

181

Saat ini saya mencoba untuk memigrasi aplikasi berbasis solr ke elasticsearch.

Saya punya permintaan lucene ini

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

Sejauh yang saya mengerti ini adalah kombinasi dari klausa HARUS dikombinasikan dengan boolean ATAU:

"Dapatkan semua dokumen yang berisi (foo DAN bilah di nama) ATAU (foo DAN bilah di info). Setelah itu hasil filter dengan kondisi kondisi = 1 dan meningkatkan dokumen yang memiliki gambar."

Saya telah mencoba menggunakan permintaan bool dengan HARUS tetapi saya gagal untuk mendapatkan boolean ATAU menjadi harus klausa. Inilah yang saya miliki:

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

Seperti yang Anda lihat, HARUS kondisi untuk "info" tidak ada.

Adakah yang punya solusi?

Terima kasih banyak.

** PEMBARUAN **

Saya telah memperbarui kueri elasticsearch dan menyingkirkan skor fungsi itu. Masalah basis saya masih ada.

Jesse
sumber
1
Ada dokumentasi yang baik pada menggabungkan ElasticSearch query di sini: elastic.co/guide/en/elasticsearch/guide/current/...
Mr.Coffee

Jawaban:

426
  • OR dieja harus
  • DAN dieja harus
  • NOR dieja should_not

Contoh:

Anda ingin melihat semua item yang ada (bulat DAN (merah ATAU biru)):

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

Anda juga dapat melakukan versi OR yang lebih kompleks, misalnya jika Anda ingin mencocokkan setidaknya 3 dari 5, Anda dapat menentukan 5 opsi di bawah "harus" dan menetapkan "minimum_harus" dari 3.

Terima kasih kepada Glen Thompson dan Sebastialonso untuk menemukan di mana sarang saya tidak benar sebelumnya.

Terima kasih juga kepada Fatmajk karena menunjukkan bahwa "istilah" menjadi "cocok" di ElasticSearch 6.

Daniel Fackrell
sumber
2
Akankah menariknya shouldke tingkat atas bool, dan termasuk sebuah minimum_should_match: 1karya?
Sid
18
Ketika saya mencoba contoh ini, saya kembali [term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]. Apakah ini entah bagaimana versi tergantung?
DanneJ
26
Mengapa mereka tidak menambahkan contoh dan penjelasan sederhana seperti itu dalam dokumen! Contoh dari dokumentasi ini sangat membingungkan.
Nikhil Owalekar
21
Setelah 6 bulan, membaca semua dokumentasi Elastis, ini adalah pertama kalinya saya benar-benar mengerti bagaimana menerapkan logika boolean. Dokumentasi resmi kurang jelas menurut saya.
Sebastialonso
3
@ Amir Kesalahan apa yang bisa saya lakukan untuk Anda? Dalam konteks yang ditunjukkan di atas, standarnya minimum_shouldadalah 1, dan membungkusnya dalam boolhasil di grup itu benar jika setidaknya satu item cocok, salah jika tidak ada yang cocok. Motivasi saya untuk menciptakan jawaban ini adalah bahwa saya sedang memecahkan masalah seperti ini, dan dokumentasi yang tersedia dan bahkan jawaban yang dapat saya temukan di situs-situs seperti ini tidak membantu, jadi saya terus meneliti sampai saya merasa memiliki pemahaman yang cukup kuat. dari apa yang sedang terjadi. Saya dengan senang hati menyambut petunjuk konstruktif tentang bagaimana saya dapat meningkatkan jawaban lebih lanjut.
Daniel Fackrell
69

Saya akhirnya berhasil membuat kueri yang melakukan persis apa yang saya inginkan:

Kueri boolean bersarang yang difilter. Saya tidak yakin mengapa ini tidak didokumentasikan. Mungkin seseorang di sini bisa memberitahuku?

Ini pertanyaannya:

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

Dalam pseudo-SQL:

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

Harap diingat bahwa itu tergantung pada analisis bidang dokumen Anda dan pemetaan bagaimana nama = foo ditangani secara internal. Ini dapat bervariasi dari fuzzy ke perilaku ketat.

"minimum_should_match": 1 mengatakan, bahwa setidaknya salah satu dari pernyataan harus benar.

Pernyataan ini berarti bahwa setiap kali ada dokumen di resultset yang berisi has_image: 1 didorong oleh faktor 100. Perubahan ini menghasilkan urutan.

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

Selamat bersenang-senang :)

Jesse
sumber
28
Omong kosong Adakah yang punya solusi yang lebih baik? Terima kasih telah memposting ini, tapi itu terlalu rumit untuk mencapai Logical OR dalam kueri.
nackjicholson
thnx, kamu menyelamatkan hariku)
cubbiu
3
Tidak hanya permintaan ini terlalu lama, tetapi menggunakan sintaks yang sudah tidak digunakan lagi. Jawaban @ daniel-fackrell harus diterima.
Eric Alford
4
@EricAlford Jawaban dari 2015 ini didasarkan pada versi ES yang lebih lama. Jangan ragu untuk memberikan solusi yang lebih baik.
Jesse
1
Ide: Ambil alih / garpu ElasticSearch, tulis ulang dengan cara yang user-friendly, tambahkan bahasa permintaan sederhana untuk itu, MENANG! Kami hanya butuh dana. Saya di! Siapa lagi ?
Sliq
16

Ini adalah bagaimana Anda dapat membuat sarang beberapa pertanyaan bool dalam satu permintaan bool luar menggunakan Kibana ini,

bool menunjukkan kita menggunakan boolean

harus untuk DAN

seharusnya untuk OR

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

Ini adalah bagaimana Anda bisa membuat sarang permintaan di ES

Ada lebih banyak jenis dalam "bool" seperti -

  1. Saring

  2. tidak harus

niranjan harpale
sumber
Jawaban Anda benar, Tapi ini agak canggung, ini saran kecil untuk Anda jika Anda mau - Anda harus mengeditnya dengan benar. Mungkin ini memberi Anda lebih banyak seperti pada jawaban ini :) Selamat bersenang-senang.
Dhwanil Patel
6

Saya baru-baru ini harus menyelesaikan masalah ini juga, dan setelah BANYAK percobaan dan kesalahan saya datang dengan ini (dalam PHP, tetapi peta langsung ke 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]]
        ]
    ]
]

Yang memetakan sesuatu seperti ini di 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>

Kunci dari semua ini adalah minimum_should_matchpengaturan. Tanpa ini yang filterbenar - benar menimpa should.

Semoga ini bisa membantu seseorang!

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

Di mustAnda perlu menambahkan array kondisi permintaan yang ingin Anda kerjakan ANDdan shouldAnda perlu menambahkan kondisi permintaan yang ingin Anda kerjakanOR .

Anda dapat memeriksa ini: https://github.com/Smile-SA/elasticsuite/issues/972

alakh kumar
sumber
0

Jika Anda menggunakan parser kueri atau Lucene default Solr, Anda bisa memasukkannya ke dalam kueri string kueri:

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

Yang mengatakan, Anda mungkin ingin menggunakan permintaan boolean , seperti yang sudah Anda posting, atau bahkan kombinasi keduanya.

Radu Gheorghe
sumber