我想找到执行服务器端查询的最佳方法,通过一些初始查询条件查找 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 2和Document 3,因为在所有id=aa1234的文档中,Document 2 具有最高(max)version,并且在 id=cc1234 的所有文档中,文档 3 具有最高(max)version。
如果有一种方法可以直接从 Java API 执行此操作,那将是理想的选择,但经过研究后,我们似乎必须使用 ServerEvaluationCall 发送 JavaScript/XQuery 块。
我已经研究过使用 JSearch reduce 函数,但无法首先按 id 对它们进行分组,它只会返回包含最高(最大)版本的单个文档。在上面的示例中,它只返回文档 2,这不是我们需要的。因此,如上所述,我们仅过滤 Java 端的文档组。
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())
您可以迭代搜索结果,并捕获对象中每个
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))
要在 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
} ]