MarkLogic node.js api - 按总和分组
MarkLogic node.js api - group by sum
类似于我的问题:
我在 Marklogic 中有包含字段 name 和 amount 的文档。我想获得每个名字的总金额。基本上 SQL 就是
select name, sum(amount) from table group by name
对于 name 和 amount,我有 range indexes。
为了获得总和,文档建议使用 valuesBuilder.fromIndexes('amount').aggregates('sum') 之类的东西,但这只会得到所有的总和记录,而不是我想要的每个名字。
有什么建议吗?
我认为没有开箱即用的分组依据,但您可以构建一个扩展程序来执行此操作。我做了一些这样的示例文档:
declareUpdate();
for (let index=0; index < 1000; index++) {
xdmp.documentInsert(
'/values' + index + '.json',
{
"name": "val" + (xdmp.random(2) + 1),
"amount": xdmp.random(2) + 1
}
)
}
我在查询控制台中 运行 此代码:
'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
}
我想这就是您要找的。您需要的其他内容:
- docs on creating a REST extension
- calling a REST extension from the Node.js Client API
- 并且您需要在
name
(字符串)和 count
(整数)上建立 运行ge 索引。
作为戴夫建议的替代方案,您可以在 Node.js 中做类似的事情,但同样,work/code 必须由您开发。
选项 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
调用它
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();
类似于我的问题:
我在 Marklogic 中有包含字段 name 和 amount 的文档。我想获得每个名字的总金额。基本上 SQL 就是
select name, sum(amount) from table group by name
对于 name 和 amount,我有 range indexes。 为了获得总和,文档建议使用 valuesBuilder.fromIndexes('amount').aggregates('sum') 之类的东西,但这只会得到所有的总和记录,而不是我想要的每个名字。
有什么建议吗?
我认为没有开箱即用的分组依据,但您可以构建一个扩展程序来执行此操作。我做了一些这样的示例文档:
declareUpdate();
for (let index=0; index < 1000; index++) {
xdmp.documentInsert(
'/values' + index + '.json',
{
"name": "val" + (xdmp.random(2) + 1),
"amount": xdmp.random(2) + 1
}
)
}
我在查询控制台中 运行 此代码:
'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
}
我想这就是您要找的。您需要的其他内容:
- docs on creating a REST extension
- calling a REST extension from the Node.js Client API
- 并且您需要在
name
(字符串)和count
(整数)上建立 运行ge 索引。
作为戴夫建议的替代方案,您可以在 Node.js 中做类似的事情,但同样,work/code 必须由您开发。
选项 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
调用它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();