elasticsearch bool sorgu birleştirmek OR ile gerekir


181

Şu anda elasticsearch için solr tabanlı bir uygulama taşımak için çalışıyorum.

Bu lucene sorgusu var

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

Bildiğim kadarıyla bu boolean OR ile birlikte MUST yan tümceleri bir kombinasyonudur:

"(Foo AND bar adında) VEYA (foo AND bar bilgi) içeren tüm dokümanları alın. Bundan sonra sonuçları koşul durumu = 1'e göre filtreleyin ve görüntü içeren dokümanları artırın."

ZORUNLU bir bool sorgusu kullanmaya çalışıyorum ama boolean OR zorunluluk cümleleri içine almak için başarısız. İşte ne var:

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

Gördüğünüz gibi, "bilgi" için ZORUNLU koşullar eksik.

Herkesin bir çözümü var mı?

Çok teşekkür ederim.

** GÜNCELLEME **

Elasticsearch sorgumu güncelledim ve bu fonksiyon skorundan kurtuldum. Temel sorunum hala var.


1
ElasticSearch birleştirerek iyi bir dokümantasyon var burada sorguları geçerli: elastic.co/guide/en/elasticsearch/guide/current/...
Mr.Coffee

Yanıtlar:


426
  • YA yazıldığından gerektiği
  • VE yazıldığından gerekir
  • NOR yazıldığından should_not

Misal:

Tüm öğeleri görmek istiyorsunuz (yuvarlak VE (kırmızı VEYA mavi)):

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

OR'nin daha karmaşık sürümlerini de yapabilirsiniz; örneğin, 5 üzerinden en az 3 eşleştirmek istiyorsanız, "must" altında 5 seçenek belirleyebilir ve "minimum_should" değerini 3 olarak ayarlayabilirsiniz.

Glen Thompson ve Sebastialonso'ya yuvalamamın daha önce tam olarak nerede olmadığını buldukları için teşekkürler.

Fatmajk'e aynı zamanda, ElastikSearch 6'da "terimin" "eşleşme" olduğuna dikkat çektiği için teşekkür ederiz.


2
shouldÜst seviyeye çekmek boolve bir minimum_should_match: 1iş dahil mi?
Sid

18
Bu örneği denediğimde geri dönüyorum [term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]. Bu bir şekilde bağımlı mı?
DanneJ

26
Neden belgelere böyle basit bir örnek ve açıklama eklemiyorlar! Belgelerden örnek çok kafa karıştırıcı.
Nikhil Owalekar

21
6 ay sonra, tüm Elastik belgeleri okurken, bu boolean mantığının nasıl uygulanacağını ilk kez anlıyorum. Resmi belgeler bana göre net değil.
Sebastialonso

3
@Amir Sizin için hangi hataları temizleyebilirim? Yukarıda gösterilen bağlamda, varsayılan minimum_shoulddeğer 1'dir ve boolbu gruptaki sonuçlarda en az bir öğe eşleşirse true, hiçbiri eşleşmiyorsa false olur. Bu cevabı oluşturmak için motivasyonum tam olarak bu tür bir problemi çözmemdi ve mevcut belgeler ve bunun gibi sitelerde bulabileceğim cevaplar en iyi ihtimalle yararsızdı, bu yüzden oldukça sağlam bir kavrayışa sahip olduğumu hissedene kadar araştırmaya devam ettim. neler olduğuna dair. Cevabı nasıl daha da geliştirebileceğime dair herhangi bir yapıcı göstergeyi memnuniyetle karşılıyorum.
Daniel Fackrell

69

Sonunda tam olarak ne istediğini yapan bir sorgu oluşturmayı başardı:

Filtre uygulanmış iç içe boolean sorgusu. Bunun neden belgelenmediğinden emin değilim. Belki burada biri bana söyleyebilir?

İşte sorgu:

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

Yalancı SQL'de:

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

Lütfen ad = foo'nun dahili olarak nasıl ele alınacağının belge alanı analizinize ve eşlemelerinize bağlı olduğunu unutmayın. Bu, bulanıktan katı davranışa kadar değişebilir.

"minimum_should_match": 1, must ifadelerinden en az birinin doğru olması gerektiğini söylüyor.

Bu ifadeler, sonuç kümesinde has_image: 1 içeren bir belge olduğunda, bunun faktör 100 tarafından artırıldığı anlamına gelir. Bu, sonuç sırasını değiştirir.

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

İyi eğlenceler arkadaşlar :)


28
Kutsal saçmalık. Daha iyi bir çözümü olan var mı? Bunu gönderdiğiniz için teşekkür ederiz, ancak bu bir sorguda Mantıksal OR elde etmek için kesinlikle çok fazla karmaşıklıktır.
nackjicholson

thnx, günümü kurtardın)
cubbiu

3
Bu sorgu gereksiz yere uzun sürmekle kalmaz, kullanım dışı sözdizimi kullanır. @ daniel-fackrell yanıtı kabul edilmelidir.
Eric Alford

4
@EricAlford 2015'teki bu yanıt ES'nin önceki bir sürümüne dayanmaktadır. Daha iyi bir çözüm sunmaktan çekinmeyin.
Jesse

1
Fikir: Elastik Arama'yı ele geçirin, kullanıcı dostu bir şekilde yeniden yazın, basit bir sorgu dili ekleyin, WIN! Sadece finansmana ihtiyacımız var. Varım! Başka kim ?
Sliq

16

Bu, Kibana'yı kullanarak bir dış bool sorgusunda birden fazla bool sorgusunu iç içe yerleştirebilirsiniz,

bool , boolean kullandığımızı gösterir

zorunluluk içindir AND

Should içindir 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" : {} 
                                 }     
                               ]
                          }
                 }
             ]
        }
    }
}

ES'de bir sorguyu bu şekilde iç içe yerleştirebilirsiniz

"Bool" gibi daha fazla türü vardır -

  1. filtre

  2. Yapmamalısın


Cevabınız tam olarak doğru, Ama biraz beceriksiz, isterseniz sizin için küçük bir öneri - düzgün bir şekilde düzenlemelisiniz. Muhtemelen size bu yanıtta olduğu gibi daha fazlasını verir :) İyi günler.
Dhwanil Patel

6

Son zamanlarda bu sorunu da çözmek zorunda kaldım ve bir çok deneme yanılma işleminden sonra bunu buldum (PHP'de, ancak doğrudan DSL ile eşleşiyor):

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

Hangi SQL'de böyle bir şey eşler:

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>

Tüm bu anahtar minimum_should_matchayarı. Bu olmadan filtertamamen geçersiz kılar should.

Umarım bu birine yardımcı olur!


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

Üzerinde mustçalışmak istediğiniz sorgu koşulu dizisini eklemeniz gerekir ANDve içinde çalışmak istediğiniz shouldsorgu koşulu eklemeniz gerekir OR.

Bunu kontrol edebilirsiniz: https://github.com/Smile-SA/elasticsuite/issues/972


0

Solr'un varsayılan veya Lucene sorgu ayrıştırıcısını kullanıyorsanız, hemen hemen her zaman bir sorgu dizesi sorgusuna koyabilirsiniz :

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

Bununla birlikte, daha önce yayınladığınız gibi bir boole sorgusu veya hatta ikisinin bir kombinasyonunu kullanmak isteyebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.