Vraag Hoe geneste AND- en OR-filters in ElasticSearch te maken?


Mijn filters zijn gegroepeerd in categorieën. Ik wil documenten ophalen waar een document kan overeenkomen met elk filter in een categorie, maar als twee (of meer) categorieën zijn ingesteld, moet het document overeenkomen met alle filters in ALLE categorieën.

Indien geschreven in pseudo-SQL zou het zijn:

SELECT * FROM Documents WHERE (CategoryA = 'A') AND (CategoryB = 'B' OR CategoryB = 'C')

Ik heb geneste filters geprobeerd zoals:

{
    "sort": [{
        "orderDate": "desc"
    }],
    "size": 25,
    "query": {
        "match_all": {}
    },
    "filter": {
        "and": [{
            "nested": {
                "path":"hits._source",
                "filter": {
                    "or": [{
                        "term": {
                            "progress": "incomplete"
                        }
                    }, {
                        "term": {
                            "progress": "completed"
                        }
                    }]
                }
            }
        }, {
            "nested": {
                "path":"hits._source",
                "filter": {
                    "or": [{
                        "term": {
                            "paid": "yes"
                        }
                    }, {
                        "term": {
                            "paid": "no"
                        }
                    }]
                }
            }
        }]
    }
}

Maar blijkbaar begrijp ik de ES-syntaxis niet helemaal. Is dit op de goede weg of moet ik een ander filter gebruiken?


12
2018-04-02 12:22


oorsprong


antwoorden:


Dit zou het moeten zijn (vertaald uit gegeven pseudo-SQL)

{
   "sort": [
      {
        "orderDate": "desc"
      }
    ],
    "size": 25,
    "query":
    {
        "filtered":
        {
            "filter":
            {
                "and":
                [
                    { "term": { "CategoryA":"A" } },
                    {
                        "or":
                        [
                            { "term": { "CategoryB":"B" } },
                            { "term": { "CategoryB":"C" } }
                        ]
                    }
                ]
            }
        }
    }
}

Ik realiseer me dat je facetten niet noemt, maar alleen omwille van de volledigheid:

U kunt ook een filter als de basis (zoals jij deed) in plaats van een filtered query (zoals ik deed). De resulterende json is bijna identiek met het verschil:

  • een gefilterde zoekopdracht filtert zowel de hoofdresultaten als de facetten
  • een filter filtert alleen de hoofdresultaten NIET de facetten.

Ten slotte hebben geneste filters (die u probeerde te gebruiken) geen betrekking op 'nestingfilters' zoals u leek te geloven, maar hadden betrekking op filteren op geneste documenten (bovenliggend-kind)


9
2018-04-02 20:10



Hoewel ik je structuur niet volledig begrijp, is dit misschien wat je nodig hebt.

Je moet boom denken. U maakt een bool waarin u (= en) de ingesloten bools moet vervullen. Elke ingesloten checkt of het veld niet bestaat of anders (gebruik moet hier in plaats van must), het veld moet (hier termen) een van de waarden in de lijst zijn.

Weet niet zeker of er een betere manier is en weet de prestaties niet.

{
    "sort": [
        {
            "orderDate": "desc"
        }
    ],
    "size": 25,
    "query": {
        "query": {           #
            "match_all": {}  # These three lines are not necessary
        },                   #
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "bool": {
                                "should": [
                                    {
                                        "not": {
                                            "exists": {
                                                "field": "progress"
                                            }
                                        }
                                    },
                                    {
                                        "terms": {
                                            "progress": [
                                                "incomplete",
                                                "complete"
                                            ]
                                        }
                                    }
                                ]
                            }
                        },
                        {
                            "bool": {
                                "should": [
                                    {
                                        "not": {
                                            "exists": {
                                                "field": "paid"
                                            }
                                        }
                                    },
                                    {
                                        "terms": {
                                            "paid": [
                                                "yes",
                                                "no"
                                            ]
                                        }
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        }
    }
}

3
2018-04-02 16:11