gpt4 book ai didi

javascript - 聚合或 Map Reduce 以创建规范化的 'Unique Paying Users Per Vendor'

转载 作者:可可西里 更新时间:2023-11-01 10:43:44 26 4
gpt4 key购买 nike

我正在尝试使用 Map Reduce 或 Mongodb 中的聚合框架为每个 vendor 的唯一付费用户创建一个报告。唯一的问题是总数需要标准化,这样每个用户在他/她购买的所有 vendor 中总共贡献 1。例如

{
"account": "abc",
"vendor": "amazon",
},
{
"account": "abc",
"vendor": "overstock",
},
{
"account": "ccc",
"vendor": "overstock",
}

会产生

{
"vendor": "amazon",
"total" : 0.5
},
{
"vendor": "overstock",
"total": 1.5
}

在这里,我们看到用户“abc”进行了两次购买并且对两个 vendor 的贡献相同。我们还看到,总结 vendor 总数将等于我们唯一的付费用户。

我天真的方法分四步执行此聚合。

1. For each user, store number of purchases by vendor in a map.
2. For each user, sum up total purchases and divide each vendor purchases by total.
3. Perform an additive merge of each users normalized purchase map into a final vendor map.

这种方法适用于较小的数据集,但速度较慢,而且在处理较大的数据集时会耗尽内存。

使用聚合框架,我已经弄清楚了如何计算总用户数,但采用的是标准化方法。

agg = this.db.aggregate(
[
{
$group :
{
_id :
{
vendor : '$vendor',
user : '$account'
},
total :
{
$sum : 1
}
}
}
]);

var transformed = {};
for( var index in agg.result)
{
var entry = agg.result[index];

var vendor= entry._id.vendor;
if(!transformed[vendor])
{
transformed[vendor] = 0;
}
transformed[vendor] += 1;
}

我如何重组此查询以规范化用户总数?

最佳答案

有几种方法可以应用于 .aggregate().mapReduce()方法,它们的效率当然会有所不同,这与数据的整体大小有关。

首先使用聚合,您将需要像您所做的那样获取每个“vendor ”的总数,但随后您将需要每个用户的总体总数才能计算出您的百分比。因此,考虑到我们将不得不创建和$unwind,分组操作的效率可能会有所不同。数组:

db.collection.aggregate([
{ "$group": {
"_id": { "account": "$account", "vendor": "$vendor" },
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.account",
"purch": { "$push": { "vendor": "$_id.vendor", "count": "$count" } },
"total": { "$sum": "$count" },
}},
{ "$unwind": "$purch" },
{ "$project": {
"vendor": "$purch.vendor",
"total": {
"$divide": [ "$purch.count", "$total" ]
}
}},
{ "$group": {
"_id": "$vendor",
"total": { "$sum": "$total" }
}}
])

mapReduce 方法必须分两步运行,首先减少用户对 vendor 的响应,然后减少 vendor :

db.collection.mapReduce(
function () {
emit(
this.account,
{
"data": [{
"vendor": this.vendor,
"count": 1,
}],
"total": 1,
"seen": false
}
);
},
function (key,values) {

var reduced = { data: [], total: 0, seen: true };

values.forEach(function(value) {
value.data.forEach(function(data) {
var index = -1;
for (var i = 0; i <=reduced.data.length-1; i++) {

if ( reduced.data[i].vendor == data.vendor ) {
index = i;
break;
}
}

if ( index == -1 ) {
reduced.data.push(data);
} else {
if (!value.seen)
reduced.data[index].count += data.count;
}
});
});

reduced.data.map(function(x) {
reduced.total += x.count;
});

return reduced;
},
{
"out": { "replace": "output" },
"finalize": function (key,value) {

var result = {
data: []
};

result.data = value.data.map(function(x) {
var res = { };
res["vendor"] = x.vendor;
res["total"] = x.count / value.total;
return res;
});

return result;
}
}
)

关于输出的第二部分:

db.output.mapReduce(
function () {
this.value.data.forEach(function(data){
emit( data.vendor, data.total );
});
},
function(key,values) {
return Array.sum( values );
},
{ "out": { "inline": 1 } }
)

所以这取决于你的数据大小。 mapReduce 方法会更慢并且需要输出到一个集合然后再次运行聚合。

另一方面,聚合框架方法通常应该运行得更快,但取决于 vendor 数组可以为每个用户提供的大小,它可能会减慢速度。

关于javascript - 聚合或 Map Reduce 以创建规范化的 'Unique Paying Users Per Vendor',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24306876/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com