【问题标题】:Fast elasticsearch CASE WHEN THEN ELSE equivalent?Fast elasticsearch CASE WHEN THEN ELSE 等效?
【发布时间】:2016-08-18 09:06:08
【问题描述】:

我需要在 Elasticsearch 中构建一个独占的分桶聚合(即,将文档分配给第一个存储桶以满足条件,而不是所有满足条件的存储桶,因为过滤器可能重叠 - 这与 CASE WHEN 的行为相同在 SQL 环境中使用 THEN ELSE)。目前我正在使用Filters Aggregation 加上Bool Query/Filter 来实现我想要的。这个想法是使用“Bool Query”的“must”和“must_not”部分,其中“must”是我的过滤器,“must_not”是之前已经使用过的所有其他过滤器的集合。一个例子是:

GET _search
{
    "query":{"match_all":{}},
    "size":0,
    "aggs":{
        "bin_1": {
            "filter": {
                "bool": {
                    "must": { <filter1> },
                    "must_not": { <empty> }
                }
            }
        },
        "bin_2": {
            "filter": {
                "bool": {
                    "must": { <filter2> },
                    "must_not": { <filter1> }
                }
            }
        },
        "bin_3": {
            "filter": {
                "bool": {
                    "must": { <filter3> },
                    "must_not": { <filter1>, <filter2> }
                }
            }
        },
        "bin_else": {
            "filter": {
                "bool": {
                    "must": { <empty> },
                    "must_not": { <filter1>, <filter2>, <filter3> }
                }
            }
        }
    }
}

在关系方法中,CASE WHEN 子句可以实现同样的效果,如下所示:

CASE WHEN <filter1> THEN <bin_1>
     WHEN <filter2> THEN <bin_2>
     WHEN <filter3> THEN <bin_3>
     ELSE <bin_else>
END

这种方法的问题在于,我添加的存储桶越多,它就越慢(在我的实际情况中,我什至有嵌套的存储桶)。在 Elastic 中是否有任何语言支持像这样的独占分桶?或者任何其他更快的方法会产生相同的结果?

谢谢!

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    我认为解决方案是脚本字段。它将使用 if else 逻辑,因此不会使用额外的条件。只是我不知道您使用的是哪种过滤器,但应该可以实现我认为的任何东西。我将在这里写相当于

    SELECT
    CASE WHEN <filter1> THEN <bin_1>
         WHEN <filter2> THEN <bin_2>
         ELSE <bin_else>
    END as binning
    FROM SOMETHING
    

    使用无痛语言的脚本字段实现。如此处所述:

    https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html 在这里无痛: https://www.elastic.co/guide/en/elasticsearch/painless/5.6/painless-examples.html

    GET _search
    {
    "query" : { "match_all": {} },
    "script fields" : {
        "binning" : {
            "script" : {
                "lang": "painless",
                "source": "if (<filter>) {return <bin1>;} else if (<filter2>) {return <bin2>;} else {return <bin3>;}"
            }
        }
    }
    

    “过滤器”类似于: doc['my_field'].value == "value1" 其中 'my_field' 是您在过滤器中使用的字段。

    【讨论】:

    • 我没想过使用脚本字段!好主意,谢谢@Honza。你对性能有任何想法吗?我怀疑脚本字段与普通的 bool 过滤器相比非常昂贵。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 2020-11-14
    • 2015-09-03
    • 2012-12-28
    • 1970-01-01
    相关资源
    最近更新 更多