i need to aggregate my data. this would be easy if i use mongodb aggregation,, but i want to perform in client side. LoDash or Underscore should solve this...
suppose i have this data:
var data = [
{
"uId" : "u1",
"qId" : "q1",
"share" : 2,
"star" : 2,
"score" : 5
},
{
"uId" : "u1",
"qId" : "q2",
"share" : 2,
"star" : 2,
"score" : 5
}.
{
"uId" : "u2",
"qId" : "q1",
"share" : 2,
"star" : 2,
"score" : 5
},
{
"uId" : "u2",
"qId" : "q2",
"share" : 3,
"star" : 3,
"score" : 7
},
{
"uId" : "u3",
"qId" : "q1",
"share" : 3,
"star" : 3,
"score" : 7
},
{
"uId" : "u3",
"qId" : "q2",
"share" : 3,
"star" : 3,
"score" : 7
}
]
i need this result:
result = [
{
"uId" : "u3",
"qId" : 2,
"share" : 6,
"star" : 6,
"score" : 14
},
{
"uId" : "u2",
"qId" : 2,
"share" : 5,
"star" : 5,
"score" : 12
}
]
it sort by highest score and limit the result to only show 2 results
thank You...
You could also do this in underscore.
_.sortBy(data, 'score').reverse().splice(0, 2);
not sure how performant the reverse would be though.
EDIT:
got it without the reverse:
_.sortBy(data, function (el) { return -el.score; }).splice(0, 2);
You can use lodash for it :
_.map(_.sortByOrder(data, ['score'], ['desc']), _.values).slice(0,2);
First it will create a sorted array and then limit the result to have only two results.
Related
How to create collection in mongodb with specific uuid or update the uuid ?
db.runCommand( { listCollections: 1.0 })
"uuid" : UUID("8d1e5add-9e49-4ff5-af4f-abf12e40b078")
Adding details:
When I create a collection mongodb generate automatically uuid and if this is replicaSet the uuid is replicated to all SECONDARY members via the oplog:
PRIMARY> use test
PRIMARY> db.createCollection("theTest")
PRIMARY> use local
PRIMARY> db.oplog.rs.find({}).sort({$natural:-1})
{ "ts" : Timestamp(1632477826, 1), "t" : NumberLong(56), "h" : NumberLong("8154379731463656698"), "v" : 2, "op" : "c", "ns" : "test.$cmd", "ui" : UUID("7710a307-020a-48bf-916c-db94544f8586"), "wall" : ISODate("2021-09-24T10:03:46.145Z"), "o" : { "create" : "theTest", "idIndex" : { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.theTest" } } }
But I would like to know if there is an option this UUID to be created with command or updated ?
Maybe there is an option to apply oplog entry with modified UUID?
Thanks,
I have found the answer, for those who are interested here is the solution:
var uuid = UUID("a6c3c5c8-8424-4a06-96a1-4082c349c6f1");
var ops = [{ "op": "c","ns": "test.$cmd","ui": uuid,"o": {"create": "newTest","idIndex": {"v": 2, "key": {"_id": 1}, "name": "_id_", "ns": "test.newTest"} } }];
db.adminCommand({applyOps: ops});
I have an array of objects in the form below. Each object represents the result of a soccer game. The actual array contains far more records than what I have here. In each game, the team (home or away) that has the highest corresponding score gets 3 points and the team with the lowest score gets 0 points. If the scores are the same, each team gets 1 point. I want to create logic that aggregates the points for each unique team whether they are home or away. I would like to see different types of options (newer syntax, etc), but especially a vanilla javascript solution.
I plan to work through it as well, but I'm struggling to come up with anything succinct.
[{
"_id" : ObjectId("5a4824f3a469a068edc875e2"),
"homeTeam" : "Team1",
"homeScore" : 2,
"awayTeam" : "Team2",
"awayScore" : 1,
}
{
"_id" : ObjectId("5a4824f3a469a068edc894e9"),
"homeTeam" : "Team2",
"homeScore" : 2,
"awayTeam" : "Team3",
"awayScore" : 1,
},{
"_id" : ObjectId("5a4824f3a469a068edc554e7"),
"homeTeam" : "Team4",
"homeScore" : 1,
"awayTeam" : "Team5",
"awayScore" : 1,
}]
var data = [{
"_id" : "5a4824f3a469a068edc875e2",
"homeTeam" : "Team1",
"homeScore" : 2,
"awayTeam" : "Team2",
"awayScore" : 1,
},
{
"_id" : "5a4824f3a469a068edc894e9",
"homeTeam" : "Team2",
"homeScore" : 2,
"awayTeam" : "Team3",
"awayScore" : 1,
},{
"_id" : "5a4824f3a469a068edc554e7",
"homeTeam" : "Team4",
"homeScore" : 1,
"awayTeam" : "Team5",
"awayScore" : 1,
}];
var teamStats = {};
var i = 0;
for(;i < data.length; i++) {
// New Home team
if(teamStats[data[i].homeTeam] == undefined) {
teamStats[data[i].homeTeam] = {
name: data[i].homeTeam,
score: 0
}
}
// New Away team
if(teamStats[data[i].awayTeam] == undefined) {
teamStats[data[i].awayTeam] = {
name: data[i].awayTeam,
score: 0
}
}
// Update score
teamStats[data[i].homeTeam].score += data[i].homeScore;
teamStats[data[i].awayTeam].score += data[i].awayScore;
}
// teamStats contains a scores of all teams
This question already has answers here:
How to get multi matching filters count in mongoDB
(1 answer)
Mongo Aggregation : $group and $project array to object for counts
(1 answer)
MongoDB: Counting how many of each distinct values there are?
(1 answer)
MongoDB group and sum with id as key
(2 answers)
Closed 5 years ago.
I'm completely new at JS so i'm having some big issues using map reduce with mongodb by my lack of knowledge, I have this collection called dailyAlerts:
{
"_id" : 25,
"title" : "Other… Title Test Polygon 2",
"alertDescription" : "Other… Description Test Polygon 2",
"alertDateTime" : 1507784400100,
"alertLatitude" : 20.5774756,
"alertLongitude" : -103.3795262,
"alertType" : 9,
"userName" : "Azgad",
"photoLink" : "www.google.com",
"videoLink" : "www.google.com",
"__v" : 0
}{
"_id" : 26,
"title" : "Other… Title Test Polygon 4",
"alertDescription" : "Other… Description Test Polygon 4",
"alertDateTime" : 1507784400100,
"alertLatitude" : 20.5774756,
"alertLongitude" : -103.3795262,
"alertType" : 5,
"userName" : "Azgad",
"photoLink" : "www.google.com",
"videoLink" : "www.google.com",
"__v" : 0
}
{
"_id" : 27,
"title" : "Other… Title Test Polygon 6",
"alertDescription" : "Other… Description Test Polygon 6",
"alertDateTime" : 1507784400500,
"alertLatitude" : 20.5774756,
"alertLongitude" : -103.3795262,
"alertType" : 1,
"userName" : "Azgad",
"photoLink" : "www.google.com",
"videoLink" : "www.google.com",
"__v" : 0
}
The important field here is "alertType", I want to use map reduce to give me the count of all alerts based on the alertType (Values available are 1-9), othewrise put 0 if no documents for that alertType are found, also I need to show me the total of all the documents processed to insert them in another collections, something like this:
{
"_id" : 4,
"dateRecord" : 3500,
"type1Count" : 0,
"type2Count" : 10,
"type3Count" : 20,
"type4Count" : 30,
"type5Count" : 0,
"type6Count" : 50,
"type7Count" : 60,
"type8Count" : 70,
"type9Count" : 80,
"totalCount" : 320,
}
I would really appreciate your help with this.
I assume your question is not about the first two property values in your desired output. The counts can be collected with reduce like this:
var data = [{ "alertType" : 9 }, { "alertType" : 5 }, { "alertType" : 1 }];
var counts = data.reduce ( (counts, obj) => {
counts[obj.alertType]++;
return counts;
}, Array(10).fill(0) );
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This returns an array where at index k you'll find the number of occurrences where alertType = k. As arrays also have index 0, that first value will always be 0. You can of course convert this to a non-array object, or any other data structure.
controller
$scope.items = [
{"id" : 1 , "itemname" : "name_1", "comment" : "dsdsd", "price" : 5000},
{"id" : 1 , "itemname" : "name_2", "comment" : "dddd", "price": 3000},
{"id" : 3 , "itemname" : "name_3", "comment" : "sdasd", "price" : 2000},
{"id" : 4 , "itemname" : "name_4", "comment" : "asdasd", "price" : 3000},
{"id" : 5 , "itemname" : "name_5", "comment" : "asdasd", "price" : 2000}
]
$scope.addToCart=function(item){
cart.add(item);
}
service
cartObj.cart.add=function(item){
cartObj.cart.push(item);
};
<div ng-repeat="item in cart">
<div>id: {{item.id}}</div>
<div>itemname: {{item.itemname}}</div>
</div>
top code cart.html
<div ng-repeat="item in items">
<a ng-click="addToCart(item)">[ addcart ]</a>
</div>
top code index.html
Example OUTPUT
id 1
name_1 5000
name_2 3000
id 3
name_3 2000
id 4
name_4 3000
id 5
name_5 2000
You can check wether there's already an item with that id, before pushing.
let oldItem = $scope.items.find(elm => elm.id === item.id);
if(oldItem){
//you can assign the properties of `item` to the one in the list
Object.assign(oldItem, item);
}else{
$scope.items.push(item);
}
You can check if it's safe to push to an array before pushing on to it.
if ($scope.items.indexOf(item) == -1) {
$scope.items.push(item);
}
I have an array in js called: areas
var areas = [
["Id" : 1, "Date" : "2016-04-01", "Name" : "Ramon"],
["Id" : 2, "Date" : "2016-04-01", "Name" : "Ester"],
["Id" : 3, "Date" : "2016-04-01", "Name" : "Sandy"],
["Id" : 4, "Date" : "2016-04-02", "Name" : "Ruiz"],
["Id" : 5, "Date" : "2016-04-03", "Name" : "Mark"],
["Id" : 6, "Date" : "2016-04-04", "Name" : "Vadim"],
["Id" : 7, "Date" : "2016-04-06", "Name" : "Vanny"],
["Id" : 8, "Date" : "2016-04-09", "Name" : "John"]
]
for example to before that I have an filter in ajax which will classify them by date and when
I am doing for:
for (var i = 0; i < areas.length; i++ ){
console.log("Date " + areas[i].Date + " Name " + areas[i].Name);
}
Output will be this
Date 2016-04-01 Name Ramon
Date 2016-04-01 Name Ester
Date 2016-04-01 Name Sandy
Date 2016-04-02 Name Ruiz
But I want if it is the same date to filter by Name
In this way:
Date 2016-04-01 Name Ester
Date 2016-04-01 Name Ramon
Date 2016-04-02 Name Ruiz
Date 2016-04-01 Name Sandy
I need to make another loop or how?
Thanks
https://jsfiddle.net/whr4taug/
Filter an array by date and after that by Name in JavaScript
your question speak for itself - you need filter function, which js has - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
And it can do all sorting in one loop. Or you can add multiple functions, each with it's sorting
var areas = [
{"Id" : 1, "Date" : "2016-04-01", "Name" : "Ramon"},
{"Id" : 2, "Date" : "2016-04-01", "Name" : "Ester"},
{"Id" : 3, "Date" : "2016-04-01", "Name" : "Sandy"},
{"Id" : 4, "Date" : "2016-04-02", "Name" : "Ruiz"},
{"Id" : 5, "Date" : "2016-04-03", "Name" : "Mark"},
{"Id" : 6, "Date" : "2016-04-04", "Name" : "Vadim"},
{"Id" : 7, "Date" : "2016-04-06", "Name" : "Vanny"},
{"Id" : 8, "Date" : "2016-04-09", "Name" : "John"}
]
var filtered = areas.filter(function(el){
if (el.Name == 'Ramon' && el.Date == '2016-04-01') return el;
});
console.log(filtered);
also your areas decalration is wrong (not sure if typo or not) - js doesn't have associated arrays, only objects for that purpose
If your requirement is to do it with ajax, then I'm not sure why you need js at all? Just do two ajax requests, and that's all
If you want to filter them inside for loop, just use same comparison
for (var i = 0; i < areas.length; i++ ){
if (areas[i].Name == 'Ramon' && areas[i].Date == '2016-04-01') {
console.log("Date " + areas[i].Date + " Name " + areas[i].Name);
}
}