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

MarkLogic中实现按字段分组,保留每组最大版本值的JSON文档服务端查询

服务端实现JSON文档分组并取每组最大version的方案

针对你需要先筛选JSON文档、按id分组、再返回每组version最大值对应文档的需求,以下是两种基于MarkLogic服务端的实现方案,可避免在Java端处理大量数据的传输开销:

方案一:通过ServerEvaluationCall调用XQuery实现

利用XQuery的分组语法,直接在服务端完成筛选、分组和取最大值的逻辑:

XQuery核心逻辑

xquery version "1.0-ml";
for $doc in cts:search(fn:doc(), cts:json-property-value-query("typeId", "CAR"))
let $id := $doc/id
let $version := $doc/version
group by $id
let $max-version-doc := fn:head(fn:sort($doc, (), function($d) { -$d/version }))
return $max-version-doc
  • 先通过cts:search筛选出typeId为CAR的文档
  • 按id字段分组,每组内将文档按version倒序排序,取第一个即为该组version最大的文档

Java端调用代码

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.eval.ServerEvaluationCall;
import com.marklogic.client.io.JacksonHandle;
import com.fasterxml.jackson.databind.JsonNode;

// 假设已初始化DatabaseClient实例client
ServerEvaluationCall eval = client.newServerEval();
String xquery = "xquery version \"1.0-ml\"; " +
    "for $doc in cts:search(fn:doc(), cts:json-property-value-query(\"typeId\", \"CAR\")) " +
    "let $id := $doc/id " +
    "let $version := $doc/version " +
    "group by $id " +
    "let $max-version-doc := fn:head(fn:sort($doc, (), function($d) { -$d/version })) " +
    "return $max-version-doc";

eval.xquery(xquery);
JacksonHandle resultsHandle = new JacksonHandle();
eval.eval(resultsHandle);
JsonNode results = resultsHandle.get();
// results即为包含目标文档的JSON数组

方案二:通过ServerEvaluationCall调用JavaScript实现

用JavaScript的对象分组逻辑,同样在服务端完成处理:

JavaScript核心逻辑

const docs = cts.search(cts.jsonPropertyValueQuery("typeId", "CAR")).toArray();
const groups = {};
for (const doc of docs) {
  const id = doc.id;
  // 若当前id未记录,或当前文档version更大,则更新为当前文档
  if (!groups[id] || doc.version > groups[id].version) {
    groups[id] = doc;
  }
}
// 返回所有分组的最大version文档
return Object.values(groups);

Java端调用代码

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.eval.ServerEvaluationCall;
import com.marklogic.client.io.JacksonHandle;
import com.fasterxml.jackson.databind.JsonNode;

// 假设已初始化DatabaseClient实例client
ServerEvaluationCall eval = client.newServerEval();
String jsCode = "const docs = cts.search(cts.jsonPropertyValueQuery(\"typeId\", \"CAR\")).toArray(); " +
    "const groups = {}; " +
    "for (const doc of docs) { " +
    "  const id = doc.id; " +
    "  if (!groups[id] || doc.version > groups[id].version) { " +
    "    groups[id] = doc; " +
    "  } " +
    "} " +
    "return Object.values(groups);";

eval.javascript(jsCode);
JacksonHandle resultsHandle = new JacksonHandle();
eval.eval(resultsHandle);
JsonNode results = resultsHandle.get();
// results即为包含目标文档的JSON数组

关于JSearch.reduce的局限性

JSearch的reduce是全局聚合操作,无法实现先分组再聚合的逻辑,因此只能返回全局version最大的单份文档,无法满足按id分组取每组最大值的需求,所以需要采用上述服务端分组的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:43:20