es 实现sql的 group by后如何分页?

先放json解释,再放纯净版方便copy

{
    "query": {
        ...... //搜索条件
    },
    "aggs": {
        "count": {   // COUNT(*),统计GROUP BY后的总数
            "cardinality": {
                "field": "goods_id"    // 因为我这里GROUP BY的字段是goods_id,所以就用goods_id来计数了
            }
        },
        "goods_id": {
            "terms": {
                "field": "goods_id",    // 选择GROUP BY的字段
                "size": 20    // 取出20条GROUP BY的数据。数量应设置为sql中offset+limit的数量。注:其实es聚合操作不是很支持分页,于是只能先将数据取出,再对其做分页操作,可想而知页数越往后效率越低
            },
            "aggs": {
                "group": {
                    "top_hits": {
                        "sort": [
                            {
                                "stock_num": {
                                    "order": "desc"    // GROUP BY的数据如何排序,这里是根据stock_num 降序排列
                                }
                            }
                        ],
                        "_source": {    // 对应SQL的SELECT 
                            "includes": [
                                "goods_no"    // SELECT的列
                            ]
                        },
                        "size": 1    // es聚合时需要指定返回几条数据(即返回几条同一个goods_id的数据)我们做GROUP BY操作就只要写1就完事了
                    }
                },
                "r_bucket_sort": {    // 分页操作
                    "bucket_sort": {
                        "sort": [],
                        "from": 0,   // 对上面取出的20条数据分页,等价于SQL的OFFSET
                        "size": 10   // SQL的LIMIT
                    }
                }
            }
        }
    },
    "size": 0,   // 因为是做聚合操作,所以直接无视query筛选出的数据
    "from": 0
}

纯净版

{
    "query": {
        
    },
    "aggs": {
        "count": {
            "cardinality": {
                "field": "group_by_field"
            }
        },
        "goods_id": {
            "terms": {
                "field": "group_by_field",
                "size": offset + limit
            },
            "aggs": {
                "group": {
                    "top_hits": {
                        "sort": [
                            {
                                "sort_by_field": {
                                    "order": "desc"
                                }
                            }
                        ],
                        "_source": {
                            "includes": [
                                "select_field1",
                                "select_field2"
                            ]
                        },
                        "size": 1
                    }
                },
                "r_bucket_sort": {
                    "bucket_sort": {
                        "sort": [],
                        "from": offset,
                        "size": limit
                    }
                }
            }
        }
    },
    "size": 0,
    "from": 0
}

拿到response后怎么取数据就不说了。用es作group by分页属实蛋疼,个人觉得不是很好,有条件还是多做个索引

对于一般的sql可以直接用
POST http://localhost:9200/_xpack/sql/translate
也是挺方便的,不过基本只能转换简单sql,group by不行

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐