I have an ng-repeat which returns arrays of objects like the following:
[{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}]
[{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}]
I'd like to have pull out the objects and push them into another array so they are formatted like this:
[
{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"},
{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"
}]
The goal is to use an orderBy on the array. Is it possible to restructure the JSON into this format and then access the data?
Here is my view for reference:
<div class="calDynamic" data-ng-repeat="n in [] | range:100">
<div ng-repeat="cal in calendar[n].year | filterKey:month">
<p>{{cal}}</p>
</div>
</div>
My JSON format:
{
"_id" : ObjectId("53f252537d343a9ad862866c"),
"year" : {
"December" : [],
"November" : [],
"October" : [],
"September" : [],
"August" : [],
"July" : [
{
"day" : "21",
"title" : "u",
"summary" : "u",
"description" : "ok",
"_id" : ObjectId("53f252537d343a9ad862866d")
}
],
"June" : [],
"May" : [],
"April" : [],
"March" : [],
"February" : [],
"January" : []
},
"__v" : 0
},
{
"_id" : ObjectId("53f252537d343a9ad862866c"),
"year" : {
"December" : [],
"November" : [],
"October" : [],
"September" : [],
"August" : [],
"July" : [
{
"day" : "3",
"title" : "u",
"summary" : "u",
"description" : "ok",
"_id" : ObjectId("53f252537d343a9ad862866d")
}
],
"June" : [],
"May" : [],
"April" : [],
"March" : [],
"February" : [],
"January" : []
},
"__v" : 0
}
Just elaborating my comment to answer:-
You can do this way to merge the arrays scattered across various month to 1 array.
//obj has the the array result that is the input
var temp = [];
var result = temp.concat.apply(temp,obj.map(function(itm){ //Get each object in the source array that hold the year.
return temp.concat.apply(temp, Object.keys(itm.year).map(function(key){ //Get Month for each yeah and flatten it out
return itm.year[key]; //Get day array for each of the month in each year
}));
}));
Object.keys(obj.year) ==> Will give you the months in your property Year to an array
Array.prototype.map ==> You pass in the months array and get back 2D array of days from all of months.
[].concat ==> returns array of concatenated arrays. It can take multiple arrays are argument, so we use function.apply conveniently to convert 2D to 1D.
Bin
Other simple and performance effective way always is loop through and add upon.
Array.prototype.concat allows to join two arrays into one. However, it is just javascript and has nothing to do with Angular, the way to do it is like:
var a = [{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}];
var b = [{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}];
var c = a.concat(b); // returns the concatenated array.
Related
This question already has answers here:
Sort Array by ISO 8601 date
(8 answers)
Closed 1 year ago.
const info = [{
"userID" : "aaa",
"dob" : "2021-07-23 22:30:00.000Z" <--- String
},
{
"userID" : "aaa11",
"dob" : "2021-06-10 12:30:00.000Z" <--- String
},
{
"userID" : "aaa22",
"dob" : "2021-09-23 22:30:00.000Z" <--- String
}]
I've been using sort to rearrange the list. However, I am quite stuck, sorting with the string.
info.sort((a, b) => a.dob - b.dob);
This works with the number but does not work with the string. I've been trying to look for the answer here, however, I could not figure it out how to sort with the ISO date string. How can I do this?
You can use Date as follows:
const info = [ { "userID" : "aaa", "dob" : "2021-07-23 22:30:00.000Z" }, { "userID" : "aaa11", "dob" : "2021-06-10 12:30:00.000Z" }, { "userID" : "aaa22", "dob" : "2021-09-23 22:30:00.000Z" } ];
const sorted = info.sort(({ dob: a }, { dob: b }) => new Date(a) - new Date(b));
console.log(sorted);
Another way using String#localeCompare:
const info = [ { "userID" : "aaa", "dob" : "2021-07-23 22:30:00.000Z" }, { "userID" : "aaa11", "dob" : "2021-06-10 12:30:00.000Z" }, { "userID" : "aaa22", "dob" : "2021-09-23 22:30:00.000Z" } ];
const sorted = info.sort(({ dob: a }, { dob: b }) => a.localeCompare(b));
console.log(sorted);
I have an API response coming in this format.
[{
"response_data": {
"0":{
"id" : 0,
"office" : "India",
"type" : 'Perm'
},
"1":{
id : 0,
"office" : "America",
"type" : 'Perm'
},
"2":{
id : 0,
"office" : "Europe",
"type" : 'Contract'
},
"2":{
id : 0,
"office" : "Latin America",
"type" : 'Contract'
}
}}]
I am trying to get all the office where the type is Contract. I have the json response saved in a variable like - using Chakram as
var response_json = t.body[0].response_data;
which gives me correct response in the console.log as
"0":{
"id" : 0,
"office" : "India",
"type" : 'Perm'
},
"1":{
id : 0,
"office" : "America",
"type" : 'Perm'
},
"2":{
id : 0,
"office" : "Europe",
"type" : 'Contract'
},
"2":{
id : 0,
"office" : "Latin America",
"type" : 'Contract'
}
Now how to get to the corresponding keys in inside the json and extract the information required. I tried this but it returns undefined
var length = Object.keys(response_json).length;
for(var i = 0; i<= length;i++){
console.log(response_json.i) //returns undefined
console.log((Object.keys(response_json)).id); //returns undefined.
}
I know that this can be solved using filter method if the response was an array, but how can I do the same operation in JSON object? I am looking for an optimized solution because the API returns almost 5000 objects.
If this question has already been asked, provide reference since I was not able to find any on SO.
If you want to do this with filter method then
a workaround would be to add a property length then using Array.from like below. Then you can use Array.prototype.filter method.
let o = {
'0': {
id: 0,
"office": "India",
"type": 'Perm'
},
'1': {
id: 0,
"office": "America",
"type": 'Perm'
},
'2': {
id: 0,
"office": "Europe",
"type": 'Contract'
}
};
o.length = Object.keys(o).length;
let a = Array.from(o);
let r = a.filter(({ type }) => type == 'Contract');
console.log(r);
Two major mistakes your code have one using loop up to the length of an array where index starts from 0. and second accessing an object from an array you use brackets instead of the dot. So update the code as follows:
var keys = Object.keys(response_json);
var length = keys .length;
for(var i = 0; i< length;i++){
console.log(response_json[keys[i]]);
}
On your response_json '0' , '1' all keys are in string format.
But in your for loop 'i' is integer so key is unavailable. just convert it to string you can get desired result
like console.log(response_json[''+i])
var data = [{"response_data": {
'0':{id : 0, "office" : "India", "type" : 'Perm'},
'1':{id : 0, "office" : "America","type" : 'Perm'},
'2':{ id : 0, "office" : "Europe","type" : 'Contract'},
'3':{ id : 0, "office" : "Latin America", "type" : 'Contract'}
}}];
var list = data[0]['response_data'];
var filterList = [];
for(var i in list) {
if(list.hasOwnProperty(i)) {
var type = list[i]['type'];
if(type === 'Contract') {
filterList.push(list[i]);
}
}
}
May be not better in javascript if the record is more than 5 thousand, better process it on server side.
This question already has answers here:
How to sort array inside collection record in MongoDB?
(16 answers)
Closed 4 years ago.
I want to fetch the data by sorting xm_score but it's not working with my query.
query = match.find({ '_id': 'k00012' }).sort('npi.xm_score');
I need to get the objects in npi get sorted by xm_score in this array.
I have the data as follows,
{
"term":'k00012',
"npi" : [
{
"npi" : "1003000126",
"xm_score" : 77.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
},
{
"npi" : "1003000126",
"xm_score" : 70.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
}]
}
You can simply have a custom function for sorting array
let obj = {
"term":'k00012',
"npi" : [
{
"npi" : "1003000126",
"xm_score" : 77.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
},
{
"npi" : "1003000126",
"xm_score" : 70.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
}]
}
let arr = obj.npi;
arr.sort((a,b) => {
return a.xm_score - b.xm_score
})
console.log(arr)
How do I get a nested object from a selected document?
If this is my document, which I get with Collection.findOne({ _id: 'dZXr2Pg7Ak4M5aYWF'})...
{
"_id" : "dZXr2Pg7Ak4M5aYWF",
"points" : [
{
"id" : "Gwf5BzorXyYBZSEzK",
"coordinates" : [
433,
215
],
"content" : "anything"
},
{
"id" : "iwSM98W5PD87BtcLa",
"coordinates" : [
666,
186
]
}
]
}
... I need to get the complete data of the point with the id Gwf5BzorXyYBZSEzK. So my result should look like:
result = {
"id" : "Gwf5BzorXyYBZSEzK",
"coordinates" : [
433,
215
],
"content" : "anything"
}
You can simply filter the points array, with Array.prototype.filter, like this
console.log(data.points.filter(function(obj) {
return obj.id === "Gwf5BzorXyYBZSEzK";
})[0]);
// { id: 'Gwf5BzorXyYBZSEzK' coordinates: [ 433, 215 ], content: 'anything' }
We just take the first element from the filtered result array. If you want to get all the elements, which have the specific id, then just remove the subscript.
If your environment supports ECMAScript 2015's Arrow functions, then you can write the same as
console.log(data.points.filter((obj) => obj.id === "Gwf5BzorXyYBZSEzK")[0]);
var data = {
"_id": "dZXr2Pg7Ak4M5aYWF",
"points": [{
"id": "Gwf5BzorXyYBZSEzK",
"coordinates": [433, 215],
"content": "anything"
}, {
"id": "iwSM98W5PD87BtcLa",
"coordinates": [666, 186]
}]
};
function finder(id){
for(i=0;i<data.points.length;i++){
if(data.points[i].id==id){
return data.points[i];
}
}
}
var result = finder("Gwf5BzorXyYBZSEzK");
document.write(JSON.stringify(result));
I'm trying to obtain an object like this from my mongodb, counting the OS per month:
{January: {Android: 30, iOS: 10, winPhone: 5}, February: {Android: 4, iOS: 40}, etc}.
And here is my mongoose schema:
var MySchema = new Schema({
date: {type: Date, default: Date.now},
os: String
});
Can give me someone an idea? Is there a way to create a single query to return me the entire object or should I build it piece by piece, unifying multiple queries?
Thank you!
You're probably better off using an output structure that's more natural for MongoDB where the keys are static and the values contain the data. Then you can use an aggregation pipeline to do this as:
MyModel.aggregate([
// Group the docs by month & os
{$group: {_id: {month: {$month: '$date'}, os: '$os'}, count: {$sum: 1}}},
// Group again by just month
{$group: {_id: '$_id.month', counts: {$push: {os: '$_id.os', count: '$count'}}}},
// Rename _id to month
{$project: {month: '$_id', counts: 1, _id: 0}}
], callback);
Which generates output like:
{
"result" : [
{
"counts" : [
{
"os" : "winPhone",
"count" : 2
},
{
"os" : "iOS",
"count" : 1
},
{
"os" : "Android",
"count" : 2
}
],
"month" : 1
},
{
"counts" : [
{
"os" : "iOS",
"count" : 2
},
{
"os" : "Android",
"count" : 1
}
],
"month" : 2
}
],
"ok" : 1
}
If you really want the original format you can then post-process the result to reshape it however you want.
Since you want to project values as keys in the output, you can't achieve this using the aggregation pipeline. None of the pipeline operators accept values as keys. You need to write map reduce functions. The map function that groups the records based on the year. So the year is emitted as the key. The value being each os name and 'month' in which it was sold.
The map function:
var map = function(){
emit(this.date.getFullYear(),
{"month":this.date.getMonth(),"os":this.os});
}
The reduce function for each group now aggregates the count of different types of os sold in a month for that year.
var reduce = function(id,osArr){
var result = {};
var osCount = {};
var monthNames = [ "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December" ];
for(var i=0;i<osArr.length;i++)
{
var mon = monthNames[(osArr[i].month)-1];
if(!osCount.hasOwnProperty(mon))
{
osCount[mon] = {};
}
if(osCount[mon].hasOwnProperty(osArr[i].os))
{
osCount[mon][osArr[i].os]++;
}
else
{
osCount[mon][osArr[i].os] = 1;
}
}
result[id] = osCount;
return result;
}
Call the map reduce function on the collection and dump it to a new collection named 'temp'.
var o = {};
o.map = map;
o.reduce = reduce;
o.out = { replace: 'temp' }
o.verbose = true;
ModelName.mapReduce(o, function (err, results) {
console.log(results)
})
This yields the following Sample results:
> db.temp.find({},{"value":1,"_id":0})
{ "value" : { "2013" : { "November" : { "Android" : 2, "ios" : 2, "blackberry" :
1 } } } }
{ "value" : { "2014" : { "October" : { "Android" : 3, "ios" : 2 } } } }