我有一个包含数百万个文档并且跨越数年的大型数据集。
在 MarkLogic(在查询控制台中首选)中,我想使用 JavaScript 检索所有唯一的计数,memberIDs
以及从 2020 年到2021 年更改为secondaryIDs
的文档中的计数。status
'w'
'y'
示例文档结构(collection = 'members'):
{
memberIDs: '123abc',
secondaryIDs: 'abc123',
year: 2021,
field1: 'x',
status: 'y'
},
{
memberIDs: '123abc',
secondaryIDs: 'abc123',
year: 2020,
field1: 'x',
status: 'w'
}
对于这个例子,答案是“2”。
我在“ MarkLogic中的索引”下的文档中找到了一种可能的解决方案,称为“shotgun 查询”。
我在Search Documents from two collections in MarkLogic也发现了一个类似的问题。但是,我不了解 XQuery,所以我不知道如何使其适应我的情况。
我的第一个想法是分别执行这两个查询,填充两个数组并确定两个数组中出现的 ID。但是,由于较大的查询会产生超过 200k 的文档,因此计算仍然需要很长时间。
我可以通过使用子序列来克服这个障碍。每次检索少量 URI,然后遍历 URI,从文档中检索我需要的值,并将它们添加到数组中。可悲的是,我的方法并没有真正奏效。此外,我正在创建的副产品本身可能就是一个问题。20 万个文档意味着我必须存储 400k 个字符串的数组。到目前为止我有这个,它没有中断,但我在 15 秒后停止运行。
let ids = []
while (startIdx < numFiles) {
let uris = fn.subsequence(
cts.uris("", null,
cts.andQuery([
cts.collectionQuery('members'),
cts.jsonPropertyValueQuery('year', 2021),
cts.jsonPropertyValueQuery('status', 'y')
]),
), startIdx, 50).toArray();
uris.forEach(uri => {
let docObj = uri ? cts.doc(uri).toObject() : undefined;
let memberId = docObj ? docObj.memberId : undefined;
let secondaryId = docObj ? docObj.secondaryId : undefined;
if (!ids.includes(memberId)) { ids.push(memberId) }
else if (!ids.includes(secondaryId)) { ids.push(secondaryId) }
})
startIdx += 50;
}
在 SQL 中,我可能会在两个查询结果之间进行 INNER JOIN 来解决这个问题。我可以在 MarkLogic 中使用 JavaScript API 做到这一点吗?
谢谢。