Json 文档搜索能够按字段对它们进行分组,并仅返回每个组中其他字段的最大值的文档

问题描述 投票:0回答:3

我想找到执行服务器端查询的最佳方法,通过一些初始查询条件查找 JSON 文档,然后按文档中的某个字段对所有这些文档进行分组,然后将每个组减少为仅包含一个包含以下内容的文档:另一个字段的最大整数值。

目前,我们正在使用

jsonPropertyValueQuery
的结果,然后在 Java 端进行过滤。这不是最佳选择,因为我们的一些查询可以返回数百个大型文档,并且我们希望避免数据传输开销。

假设我们从查询中找到了以下 JSON 文档

cts.jsonPropertyValueQuery("typeId", "CAR")

文档1

{
  "id": "aa1234",
  "typeId": "CAR",
  "version": 1
}

文档2

{
  "id": "aa1234",
  "typeId": "CAR",
  "version": 2
}

文档3

{
  "id": "cc1234",
  "typeId": "CAR",
  "version": 1
}

我想要一种方法来过滤/减少这些文档服务器端(而不是控制台端),让我们只返回Document 2Document 3,因为在所有id=aa1234的文档中,Document 2 具有最高(max)version,并且在 id=cc1234 的所有文档中,文档 3 具有最高(max)version

如果有一种方法可以直接从 Java API 执行此操作,那将是理想的选择,但经过研究后,我们似乎必须使用 ServerEvaluationCall 发送 JavaScript/XQuery 块。

我已经研究过使用 JSearch reduce 函数,但无法首先按 id 对它们进行分组,它只会返回包含最高(最大)版本的单个文档。在上面的示例中,它只返回文档 2,这不是我们需要的。因此,如上所述,我们仅过滤 Java 端的文档组。

json group-by marklogic reduce
3个回答
0
投票

使用 JavaScript 的解决方案

Map
Array.reduce()
:

const searchResults = cts.search(cts.jsonPropertyValueQuery("typeId", "CAR")).toArray();
const maxVersionByID = searchResults.reduce(
    (entryMap, e) => { 
      const obj = e.toObject();
      const previousVersion = entryMap.get(obj.id) ? entryMap.get(obj.id).version : -1
      if (previousVersion < parseInt(obj.version)) {
         entryMap.set(obj.id, e) 
      }
      return entryMap;
    },
    new Map()
);
Array.from(maxVersionByID.values())

0
投票

您可以迭代搜索结果,并捕获对象中每个

version
具有最高
id
的文档,然后将值作为数组返回,或转换为序列:

const maxVersionByID = { };
for (const doc of cts.search(cts.jsonPropertyValueQuery("typeId", "CAR")) ) {
  const obj = doc.toObject();
  const previousVersion = maxVersionByID[obj.id] ? parseInt(maxVersionByID[obj.id].version) : -1
  if (previousVersion < parseInt(obj.version)) {
    maxVersionByID[obj.id] = obj;
  }
}
Sequence.from(Object.values(maxVersionByID))

0
投票

要在 Java 服务器端执行此操作,您可以使用 JSON 库 Josson 来转换 JSON 文档。

https://github.com/octomix/josson

假设它是一个 JSON 数组来保存所有对象。

Josson josson = Josson.fromJsonString(
    "[" +
    "    {" +
    "        \"id\": \"aa1234\"," +
    "        \"typeId\": \"CAR\"," +
    "        \"version\": 1" +
    "    }," +
    "    {" +
    "        \"id\": \"aa1234\"," +
    "        \"typeId\": \"CAR\"," +
    "        \"version\": 2" +
    "    }," +
    "    {" +
    "        \"id\": \"cc1234\"," +
    "        \"typeId\": \"CAR\"," +
    "        \"version\": 1" +
    "    }" +
    "]");
JsonNode node = josson.getNode("group(id)@.elements.findByMax(version)");
System.out.println(node.toPrettyString());

输出

[ {
  "id" : "aa1234",
  "typeId" : "CAR",
  "version" : 2
}, {
  "id" : "cc1234",
  "typeId" : "CAR",
  "version" : 1
} ]
© www.soinside.com 2019 - 2024. All rights reserved.