I have an angular app which gets data from a JSON response.
How do i create another array, in a different format within my controller?
JSON RESPONSE:
"prices" : [
{"month" : "01", "price" : 599},
{"month" : "02", "price" : 1599},
{"month" : "03", "price" : 2599},
{"month" : "04", "price" : 3599},
]
$scope.prices = data.prices;
Into this for use in a calendar function (new object for every object returned in $scope.prices above):
$scope.events = [{
title: * * $scope.prices.price * * ,
start: new Date(y, $scope.prices.month, 1),
dow: [1, 2, 3, 4, 5, 6],
allDay: true
}];
Many thanks
UPDATE
OK, got the new structure using Array.protoype.map(), but it is placing double quotes around everything.
It is returning:
[{"title":599,"start":"1901-02-01T05:00:00.000Z","dow":[1,2,3,4,5,6],"allDay":true}
when it needs to be:
[{title:"599",start:1901-02-01T05:00:00.000Z,dow:[1,2,3,4,5,6],allDay:true}
Here is my code:
var reformattedArray = array.map(function(obj){
var rObj = {title: obj.price,start: new Date(obj.month, 1),dow:[1,2,3,4,5,6],allDay: true};
return rObj;
});
Related
I have a document.
{
"errors" : [
{
"priority" : 3,
"category" : "aaa"
"other":"nothing"
},
{
"priority" : 4,
"category" : "bbb"
"other":"nothing"
},
{
"priority" : 2,
"category" : "ccc"
"other":"nothing"
},
{
"priority" : 3,
"category" : "ddd"
"other":"nothing"
},
{
"priority" : 2,
"category" : "eee"
"other":"nothing"
}
],
"file_name" : "xxx.json",
"vehicle_id" : "esdf",
"day" : "2022-03-08"
}
I execute a command with js client.
db.wty_test.aggregate({
$project: {
'_id': 0, 'errors.priority': 1, 'errors.category': 1, 'file_name': 1, 'vehicle_id': 1,
}
})
I get the result I want.
The errors is an array containing objects.
Now I need to overwrite this command with java client(springboot-data-mongo). This is my java code.
import org.springframework.data.mongodb.core.MongoTemplate;
...
Aggregation aggregation = Aggregation.newAggregation(Aggregation.project("errors.priority", "errors.category", "file_name", "vehicle_id"));
mongoTemplate.aggregate(aggregation, "wty_test", HashMap.class).getMappedResults();
The priority and category is not in errors.
How to use java to get the same result as js?
I try the nested.But it's not what I want.
Here is a way to get the desired result.
Document projectn = new Document("$project",
new Document("_id", 0L)
.append("file_name", 1L)
.append("vehicle_id", 1L)
.append("errors",
new Document("$map",
new Document("input", "$errors")
.append("in",
new Document("priority", "$$this.priority")
.append("category", "$$this.category")
)
)
)
);
List<Document> pipeline = Arrays.asList(projectn);
List<Document> results = mongoOps.getCollection("collection_name")
.aggregate(pipeline)
.into(new ArrayList<>());
Note that this uses MongoDB Java Driver API query syntax, and Document is org.bson.Document. The conversion of the native query to Java Driver uses $map aggregation array operator (and it looks like thats the (maybe only) way).
With MongoTemplate.aggregate the code is:
Aggregation agg = newAggregation(
project()
.and(
VariableOperators.Map.itemsOf("errors")
.as("e")
.andApply(ctx -> new Document("priority", "$$e.priority").append("category", "$$e.category") ))
.as("errors")
.andExclude("_id")
.andInclude("file_name", "vehicle_id")
);
AggregationResults<Document> results = mongoOps.aggregate(agg, "collection_name", Document.class);
Alternate Method:
In case your query is just about the projection, you can use the following query using MongoTemplate#find method. This is much simpler to construct and understand:
db.collection.find(
{}, // your query filter
{ _id: 0, 'errors.category': 1, 'errors.priority': 1, file_name: 1, vehicle_id: 1 }
)
The MongoTemplate version of it:
Query query = new Query();
query.fields()
.include("errors.priority", "errors.category", "file_name", "vehicle_id")
.exclude("_id");
List<Document> results = mongoOps.find(query, Document.class, "collection_name");
You want to be using the nested() function, like so:
AggregationOperation project = Aggregation.project("file_name", "vehicle_id").
and("errors").nested(Fields.fields("priority","category"))
Aggregation aggregation = Aggregation.newAggregation(project);
List<String> projectFieldSet = Arrays.asList("errors.category","errors.priority");
List<Field> fieldList = projectFields.stream().map(f->{return Fields.field(f,f);}).collect(Collectors.toList());
ProjectionOperation projectAggOp = Aggregation.project(Fields.from(fieldList.toArray(new Field[fieldList.size()])));
How to fetch the length and individual values in javascript
here is example data
examples:
"numbers": "248001,248142",
"numbers": "588801,248742,588869"
Actuall code
{
"_id" : ObjectId("579ce69f4be1811f797fbab2"),
"city" : "",
"sdescription" : "",
"categories" : [
"5729f312d549cc3212c8393b"
],
"numbers" : "4555855,421201",
"createdAt" : ISODate("2016-07-30T17:40:47.022Z"),
"month" : 7,
"year" : 2016
}
here is my code and error
let num = numbers.split(',')
(node:5628) UnhandledPromiseRejectionWarning: TypeError: numbers.split is not a function
I have tried split to separate the values but some times it returns an error as number.split is not a function.
I want to return two things:
length: in the first example length should be 2 and in the second example
length should be 3.
2.values should get split
You need to call start from object name objectname.keyname
var obj = { "city": "", "sdescription": "", "categories": [ "5729f312d549cc3212c8393b" ], "numbers": "4555855,421201", "month": 7, "year": 2016 }
var res = obj.numbers.split(',').length;
console.log(res)
You can loop through your object and then for each element access numbers property and then split and find length
let json = [{"numbers": "248001,248142"},{"numbers": "588801,248742,588869"},{"numbers":[]}]
json.forEach(({numbers})=>{
console.log(typeof numbers === 'string' ? numbers.split(',').length : 'Not a string')
})
I got this sample data.
"array" : [
{"Id" : "1", "preferred" : false},
{"Id" : "1", "preferred" : true },
{"Id" : "2", "preferred" : false},
{"Id" : "2", "preferred" : false},]
And i would like to get out of it something like this.
"array2":[{"Id": 1, numOfTrue: 1, numOfFalse: 1},{"Id": 2, numOfTrue: 0, numOfFalse: 2}]
What i got so far is a way how to get unique id form initial array.
const unique = [...new Set(array.map(item => Id))];
Next step would be some forEach over array and comparing Id values and setting some counters for that boolean value. So before i dive into forEach solution i would like to ask if there is another way with using .filter() and .reduce() methods.
You can use reduce() to build a grouping object keyed to Id. Each time you see that Id again increment the value at the appropriate key. In the end your array will be the Object.values() of the object:
let array = [
{"Id" : "1", "preferred" : false},
{"Id" : "1", "preferred" : true },
{"Id" : "2", "preferred" : false},
{"Id" : "2", "preferred" : false}
]
let counts = array.reduce((counts, {Id, preferred}) => {
// If you haven't seen this Id yet, make a new entry
if (!counts[Id]) counts[Id] = {Id, numOfTrue: 0, numOfFalse: 0}
// increment the appropriate value:
if (preferred) counts[Id].numOfTrue++
else counts[Id].numOfFalse++
return counts
}, {})
// get the values array of the object:
console.log(Object.values(counts))
Say we have a plain javascript array of objects
[
{id : 1, name : "Hartford Whalers"},
{id : 2, name : "Toronto Maple Leafs"},
{id : 3, name : "New York Rangers"}
]
and we wanted to bring it in to immutablejs. Would it be most natural to make it into a map or a list, and how would we update a property in one of the objects? Say change the name of "Hartford Whalers" to "Carolina Hurricanes".
You should create a List of Maps for this. Immutable.js has a function Immutable.fromJS that will recursively convert JS Arrays to Immutable.List and JS Objects to Immutable.Map.
var input = [
{id : 1, name : "Hartford Whalers"},
{id : 2, name : "Toronto Maple Leafs"},
{id : 3, name : "New York Rangers"}
];
var list = Immutable.fromJS(input);
list.toString(); // => "List [ Map { "id": 1, "name": "Hartford Whalers" }, Map { "id": 2, "name": "Toronto Maple Leafs" }, Map { "id": 3, "name": "New York Rangers" } ]"
You can set the name of the first item using .setIn:
var list2 = list.setIn([0, "name"], "Carolina Hurricanes");
list2.toString(); // => "List [ Map { "id": 1, "name": "Carolina Hurricanes" }, Map { "id": 2, "name": "Toronto Maple Leafs" }, Map { "id": 3, "name": "New York Rangers" } ]"
You can set the name of any item with name = "Hartford Whalers" to "Carolina Hurricanes" :
var list3 = list.map(function(item) {
if(item.get("name") == "Hartford Whalers") {
return item.set("name", "Carolina Hurricanes");
} else {
return item;
}
});
list3.toString(); // => "List [ Map { "id": 1, "name": "Carolina Hurricanes" }, Map { "id": 2, "name": "Toronto Maple Leafs" }, Map { "id": 3, "name": "New York Rangers" } ]"
I disagree.
The example you give each element of the array is an object that has an { id } property. One would assume you will want to access the elements of this array via their id. thats what ids are for.
Yes the native structure is a List of Maps. Although what you want is a Map of Maps.
Why?
Think about what you will need to do to retrieve { id: 1928, "Some Team" }. You would have to iterate one-by-one through the list till you found your matching Id.
A far more efficient way to do this is create a map so you can directly "pluck" your object e.g.
const input = Immutable.fromJS({
1: {id : 1, name : "Hartford Whalers"},
2: {id : 2, name : "Toronto Maple Leafs"},
3: {id : 3, name : "New York Rangers"},
// ...
1928: {id : 1928, name : "Some Team"},
});
Then to access it all you have to do is:
const team = input.get('1928');
you need to do the initial conversion, do that server-side if its coming from an API, its called normalisation. It has the benefit of saving data as well.
This is actually where the term "map" comes from
I am implementing a ranking system. I have a collection with elements like this:
{"_id" : 1, "count" : 32}
{"_id" : 2, "count" : 12}
{"_id" : 3, "count" : 34}
{"_id" : 4, "count" : 9}
{"_id" : 5, "count" : 77}
{"_id" : 6, "count" : 20}
I want to write a query that return an element which has {"id" : 1} and 2 other neighbor elements (after sorting by count). Totally 3 elements returned.
Ex:
After sorting:
9 12 20 32 34 77
The query should return 20 32 34.
You will never get this in a single query operation, but it can be obtained with "three" queries. The first to obtain the value for "count" from the desired element, and the subsequent ones to find the "preceding" and "following" values.
var result = [];
var obj = db.collection.findOne({ "_id": 1 }); // returns object as selected
result.push(obj);
// Preceding
result.unshift(db.collection.findOne({
"$query": { "count": { "$lt": obj.count } },
"$orderby": { "count": -1 }
}));
// Following
result.push(db.collection.findOne({
"$query": { "count": { "$gt": obj.count } },
"$orderby": { "count": 1 }
}));
Asking to do this in a "single query" is essentially asking for a "join", which is something that MongoDB essentially does not do. It is a "Set Intersection" of the discrete results, and that in SQL is basically a "join" operation.