按ID检索含嵌套JSON的文档并限制嵌套数组返回条数的最佳方法
问题场景
现有如下结构的存储文档:
{ "nested_items": [ { "nested_sample0": "1", "nested_sample1": "test", "nested_sample2": "test", "nested_sample3": { "type": "type" }, "nested_sample": null }, { "nested_sample0": "1", "nested_sample1": "test", "nested_sample2": "test", "nested_sample3": { "type": "type" }, "nested_sample1": null }, "..." ], "sample1": 1233, "id": "ed68ca34-6b59-4687-a557-bdefc9ec2f4b", "sample2": "", "sample3": "test", "sample4": "test", "_ts": 1656503348 }
核心需求:按ID精确匹配检索文档时,限制返回结果中nested_items数组的返回元素条数。已知当前子查询不支持LIMIT/OFFSET语法,除拆分两次查询外,可通过以下方案实现:
实现方案
UDF截断方案
注册数组切片自定义函数,在查询返回阶段直接对目标数组做截断,UDF示例代码:function truncateArray(arr, limit) { if (!Array.isArray(arr)) return arr; return arr.slice(0, limit); }对应查询语句:
SELECT c.id, c.sample1, c.sample2, c.sample3, c.sample4, c._ts, udf.truncateArray(c.nested_items, @targetItemCount) as nested_items FROM c WHERE c.id = @queryId该方案实现简单,缺点是UDF存在额外性能开销,单文档数组体量过大时RU消耗会明显升高。
内置函数聚合裁剪方案
无需注册UDF,通过JOIN展开数组后用ROW_NUMBER窗口函数给元素打序号,过滤出符合条数要求的元素后再重组为数组,示例查询:SELECT c.id, c.sample1, c.sample2, c.sample3, c.sample4, c._ts, ARRAY( SELECT VALUE elem.detail FROM ( SELECT t AS detail, ROW_NUMBER() OVER(PARTITION BY c.id ORDER BY t.nested_sample0) AS rowNum FROM c JOIN t IN c.nested_items ) elem WHERE elem.rowNum <= @targetItemCount ) AS nested_items FROM c WHERE c.id = @queryId该方案性能优于UDF方案,注意需要指定稳定的排序字段,否则返回的数组元素顺序可能出现波动。
建模优化方案
如果nested_items数组元素普遍较多、且经常需要做分页/部分返回,长期来看最优方案是将嵌套数组拆分为独立子文档,通过主文档ID做关联,查询子文档时直接使用原生LIMIT/OFFSET语法即可,性能和RU成本表现最好,也是这类场景下的推荐建模方式。
内容的提问来源于stack exchange,提问作者Aquaelia
相关产品推荐
相关产品推荐

