我有一个JSON集合作为数组。我想按集合中的三个字段进行分组,然后返回结果以及匹配文档的计数。下面的例子有望让它更清晰。
返回了JSON文档集合:
SELECT m.id, m.name, m.marks, s.marks, e.marks,
CASE WHEN (m.marks > 75 and s.marks > 75) OR (s.marks > 75 and e.marks > 75) OR (m.marks > 75 and e.marks > 75) THEN 'Pass'
WHEN (m.marks > 75 and (s.marks > 60 OR e.marks > 60)) OR
(s.marks > 75 and (m.marks > 60 OR e.marks > 60)) OR
(e.marks > 75 and (s.marks > 60 OR m.marks > 60)) THEN 'Pass'
WHEN (m.marks < 75 and s.marks < 75 and e.marks < 75 and (m.marks < 50 or e.marks < 50 or s.marks < 50)) THEN 'Fail'
ELSE NULL END as Merit
FROM #maths m
inner join #science s
on m.ID = s.ID
inner join #English e
on m.ID = e.ID
应该在浏览器,ipAddress和uri上执行分组,然后返回分组结果以及下面的计数(我检查了几次,所以我希望下面的数字加到上面每个组合的实例中!)。
[
{
_id: 1,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 2,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 3,
browser: 'opera',
ipAddress: '222.0.888.0',
uri: 'example1.com'
},
{
_id: 4,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 5,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 6,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 7,
browser: 'opera',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
}
]
我知道使用map / reduce应该可以轻松实现这一点,但我似乎无法让我对如何做到这一点感到困惑!
提前致谢。
答案 0 :(得分:1)
使用lodash的另一种(更实用的)方法:
_(array).groupBy(v => ([v.browser, v.ipAddress, v.uri]))
.map(v => _.merge(_.omit(v[0], '_id'), {count: v.length}))
.value();
简短说明:groupBy
使用browser,ipAddress和uri创建分组。在map
语句中,我们删除了_id字段,并根据组中对象的数量添加计数。
答案 1 :(得分:0)
您可以使用单个reduce vanilla JavaScript 执行此操作:
let arr = [
{
_id: 1,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 2,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 3,
browser: 'opera',
ipAddress: '222.0.888.0',
uri: 'example1.com'
},
{
_id: 4,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 5,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 6,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 7,
browser: 'opera',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
}
]
let result = arr.reduce((_, x) => {
for(let i = 0; i < _.length; i++) {
if(_[i].browser === x.browser && _[i].ipAddress === x.ipAddress && _[i].uri === x.uri) {
_[i].count++
return _
}
}
let { _id, ...rest } = x
return [ ..._, { ...rest, count: 1 } ]
}, [])
console.log(result)
&#13;
答案 2 :(得分:0)
您可以尝试这样的事情:
var data=[{_id:1,browser:"chrome",ipAddress:"222.111.111.0",uri:"example1.com"},{_id:2,browser:"chrome",ipAddress:"222.111.111.0",uri:"example1.com"},{_id:3,browser:"opera",ipAddress:"222.0.888.0",uri:"example1.com"},{_id:4,browser:"chrome",ipAddress:"222.111.222.0",uri:"sample1.com"},{_id:5,browser:"chrome",ipAddress:"222.111.222.0",uri:"sample1.com"},{_id:6,browser:"chrome",ipAddress:"222.111.222.0",uri:"sample1.com"},{_id:7,browser:"opera",ipAddress:"222.111.222.0",uri:"sample1.com"}];
function groupBy(array, keys) {
var groups = array.reduce(function(p, c) {
var hash = keys.map(function(k){ return c[k]; }).join("|")
p[hash] = p[hash] || c;
p[hash]["count"] = (p[hash]["count"] || 0) + 1
delete p[hash]["_id"];
return p;
}, {});
var result = Object.keys(groups).map(function(x){return groups[x] })
console.log(result);
return result
}
var keys = ["browser", "ipAddress", "uri"]
groupBy(data, keys)
答案 3 :(得分:0)
如果您愿意使用lodash
(如果没有,请更好地使用),您可以执行以下操作,
var array = [
{
_id: 1,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 2,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 3,
browser: 'opera',
ipAddress: '222.0.888.0',
uri: 'example1.com'
},
{
_id: 4,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 5,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 6,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 7,
browser: 'opera',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
}
]
var res = _.reduce(array, function(acc, elem){
delete elem._id;
var obj = _.find(acc, elem)
if(obj){
obj.count++;
}
else{
elem.count = 1;
acc.push(elem);
}
return acc;
}, [])
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
答案 4 :(得分:0)
您可以使用通用的减速器生成器来实现此目的。此代码基于my previous answer to another question。您可以为其指定要分组的字段,并返回可用作减少项的计数项。
let arr = Object.freeze([
{
_id: 1,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 2,
browser: 'chrome',
ipAddress: '222.111.111.0',
uri: 'example1.com'
},
{
_id: 3,
browser: 'opera',
ipAddress: '222.0.888.0',
uri: 'example1.com'
},
{
_id: 4,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 5,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 6,
browser: 'chrome',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
},
{
_id: 7,
browser: 'opera',
ipAddress: '222.111.222.0',
uri: 'sample1.com'
}
]);
const groupByReducerCount = (group) =>
(result, row) => {
const keygroup = group.map((v) => row[v]);
const key = keygroup.join(':');
if (result[key])
result[key] ++;
else
result[key] = 1;
return result;
};
const result = arr.reduce(groupByReducerCount(['uri','browser','ipAddress']),{});
console.log(result)