You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于字段对MarkLogic 9 Optic Java API查询结果分区

用MarkLogic 9 Optic Java API实现按字段分区(保留所有行)

嘿Swati,刚好我对MarkLogic Optic API的窗口函数和聚合功能很熟悉,能帮你找到简便的解决方案,不用多次查询或者聚合丢失数据!

你的需求是按newspaper字段分区展示所有结果、保留原始行,这其实可以通过两种方式实现,对应不同的输出结构:

方式1:保留所有原始行,按分区排序并添加分区标识

这种方法完全保留总行数,给每行打上分区内的行号,同时让同分区的行连续排列,客户端拿到结果后可以轻松分组展示。核心是用窗口函数(Window Functions),这就是Optic API对应SQL PARTITION BY的等效功能。

Java代码示例

PlanBuilder op = PlanBuilder.newPlanBuilder();

ModifyPlan partitionedPlan = op.fromView(recordsSchema, recordsView)
    // 保留你原有的连接逻辑
    .joinInner(op.fromView(productsSchema, productsView), 
        op.on(op.viewCol(recordsView, "md5Digest"), op.viewCol(productsView, "md5Digest")))
    .joinInner(op.fromView(occurrencesSchema, occurrencesView), 
        op.on(op.viewCol(productsView, "md5Digest"), op.viewCol(occurrencesView, "md5Digest")))
    // 保留原有的过滤条件
    .where(op.or(
        op.and(op.contains(op.col("adDescription"), "SNACK FOODS"), op.eq(op.col("pageNumber"), 5)),
        op.and(op.eq(op.col("state"), "KY"), op.eq(op.col("issue"), "2018-01-21"))
    ))
    // 选择需要的字段,务必包含分区字段newspaper
    .select(
        op.col("newspaper"),
        op.col("pageNumber"),
        op.col("state"),
        op.col("adDescription"),
        op.col("issue")
    )
    // 添加窗口函数:按newspaper分区,生成分区内行号
    .window(
        op.partitionBy(op.col("newspaper")),
        op.col("row_in_partition").as(op.rowNumber())
    )
    // 先按newspaper排序,再按原有的issue降序,确保同分区的行排在一起
    .orderBy(op.col("newspaper"), op.desc(op.col("issue")));

查询返回的结果里,所有原始行都保留,并且按newspaper分组排列,每行还会有row_in_partition字段标记它在当前分区的位置,客户端只需要遍历结果,遇到新的newspaper值就切换分组展示即可。

方式2:直接生成结构化分组结果(分区对应行数组)

如果希望数据库直接返回类似你示例的结构(每个分区对应一个行数组),可以用groupBy配合arrayAgg聚合函数,把同分区的所有行打包成数组,虽然总行数变成分区的数量,但所有原始行数据都完整保留在数组里。

Java代码示例

PlanBuilder op = PlanBuilder.newPlanBuilder();

ModifyPlan groupedPlan = op.fromView(recordsSchema, recordsView)
    // 保留原有的连接和过滤逻辑
    .joinInner(op.fromView(productsSchema, productsView), 
        op.on(op.viewCol(recordsView, "md5Digest"), op.viewCol(productsView, "md5Digest")))
    .joinInner(op.fromView(occurrencesSchema, occurrencesView), 
        op.on(op.viewCol(productsView, "md5Digest"), op.viewCol(occurrencesView, "md5Digest")))
    .where(op.or(
        op.and(op.contains(op.col("adDescription"), "SNACK FOODS"), op.eq(op.col("pageNumber"), 5)),
        op.and(op.eq(op.col("state"), "KY"), op.eq(op.col("issue"), "2018-01-21"))
    ))
    // 选择需要的字段,包含分区字段newspaper
    .select(
        op.col("newspaper"),
        op.col("pageNumber"),
        op.col("state"),
        op.col("adDescription"),
        op.col("issue")
    )
    // 按newspaper分组,将同组的行聚合成数组
    .groupBy(op.col("newspaper"),
        op.col("rows").as(op.arrayAgg(op.map(
            op.entry("pageNumber", op.col("pageNumber")),
            op.entry("state", op.col("state")),
            op.entry("adDescription", op.col("adDescription")),
            op.entry("issue", op.col("issue"))
        )))
    )
    .orderBy(op.col("newspaper"));

这个查询的结果会是每个newspaper一行,包含一个rows数组,数组里是该分区的所有原始行数据,和你给出的示例结构完全匹配,客户端拿到后可以直接遍历每个分区展示对应的行。

关键说明

  • MarkLogic 9的Optic API完全支持窗口函数,op.window()方法就是实现SQL PARTITION BY逻辑的核心,它不会合并行,只会给每行添加分区相关的计算字段。
  • arrayAgg是Optic的聚合函数,用来把多行数据打包成数组,完美解决了你担心groupBy会合并行丢失数据的问题。

内容的提问来源于stack exchange,提问作者Swati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:42:19