类似于我的问题:MarkLogic node.js api - group by and sort by count
我在Marklogic中有文件 name 和 amount 。我想得到每个名字的总金额。基本上在SQL中它将是
select name, sum(amount) from table group by name
name 和 amount 的范围索引。 为了获得总和聚合,文档建议类似 valuesBuilder.fromIndexes('amount')。聚合('sum'),但这只得到所有记录的总和,而不是像我想要的每个名称
有什么建议吗?
答案 0 :(得分:2)
我不认为这是一个开箱即用的群体,但你可以建立一个扩展来做到这一点。我做了一些样本文档:
declareUpdate();
for (let index=0; index < 1000; index++) {
xdmp.documentInsert(
'/values' + index + '.json',
{
"name": "val" + (xdmp.random(2) + 1),
"amount": xdmp.random(2) + 1
}
)
}
我在Query Console中运行了这段代码:
'use strict';
var jsearch = require('/MarkLogic/jsearch.sjs');
var tuples =
jsearch.tuples(
[
cts.jsonPropertyReference('name'),
cts.jsonPropertyReference('amount', ["type=int"])
]
)
.slice(0, 1000) // get all the values
.map({frequency: "item", names: ['name', 'count', 'frequency']})
.result();
tuples
.reduce(function(acc, current, index, array) {
acc[current.name] = parseInt(current.count, 10) * current.frequency;
return acc;
}, {});
这让我得到了回应:
{
"val1": 381,
"val2": 351,
"val3": 324
}
我认为这就是您正在寻找的东西。你需要的其他东西:
name
(字符串)和count
(int)上的范围索引。 答案 1 :(得分:2)
作为Dave建议的替代方案,您可以在Node.js中执行类似操作,但同样,工作/代码必须由您开发。
选项1)
db.values.read(
vb.fromIndexes('name', 'amount')
)
.result()
这里的代码会创建名称和金额的共同出现 - 然后您可以去处理这些信息。
选项2)
从索引中获取名称,然后将该信息提供给另一个获取金额并将其汇总的函数:
function getNames() {
return db.values.read(
vb.fromIndexes('name')
)
.result();
}
function getSum(names) {
const promises = names.map(name => {
return db.values.read(
vb.fromIndexes('amount')
.aggregates('sum')
.where(vb.parsedFrom(`name:${name}`,
vb.parseBindings(vb.value('name', vb.bind('name')))
))).result();
});
return Promise.all(promises);
};
getNames()
.then(response => {
const names = response['values-response'].tuple.map(name => name['distinct-value'].toString());
console.log(names); //this will hold all the names
return getSum(names);
})
.then(response => {
const sums = response.map(r => {
return r['values-response']['aggregate-result'][0];
}).map(s => s._value);
console.log(sums); //this will hold all the sums
})
.catch(error => console.log(error));
选项3)
Dave建议 - 创建SJS扩展,并从Node.js调用它
答案 2 :(得分:1)
来自Tamas和Dave的好建议的一个脚注 - 在MarkLogic 9中,您可以使用类似于以下示例的方式使用Optic API(在本例中,使用服务器端JavaScript):
'use strict';
const op = require('/MarkLogic/optic');
const employees = op.fromView(null, 'employees');
const expenses = op.fromView(null, 'expenses');
employees
.joinInner(expenses, op.on(
employees.col('EmployeeID'), expenses.col('EmployeeID')
))
.groupBy('LastName', op.sum('Total', 'Amount'))
.orderBy('Total')
.where(op.lt(199, op.col('Total')))
.result();