Modifying keys for an object that has arrays of object - javascript

There is an object where each key is an array of objects.
For example, in the following example data is an object having keys where each key is an array of object(s):
{
"status": 200,
"message": "Successful",
"data": {
"manual": [
{
"vendor_id": 1,
"price": 4590,
"discounts": {
"micro": 0,
"macro": 120
},
"vendor": "Vendor 1",
"customer_rating": "3.0/5",
"sla_compliance": 90,
"system_flag": "Green"
}
],
"nearest": [
{
"vendor_id": 1,
"price": 4590,
"discounts": {
"micro": 0,
"macro": 120
},
"vendor": "Vendor 1",
"customer_rating": "3.0/5",
"sla_compliance": 90,
"system_flag": "Green"
}
],
"auto": [
{
"vendor_id": 1,
"price": 4590,
"discounts": {
"micro": 0,
"macro": 120
},
"vendor": "Vendor 1",
"customer_rating": "3.0/5",
"sla_compliance": 90,
"system_flag": "Green"
}
],
"ticket_id": 72
}
}
I need to add/delete keys from the each object that is inside the array. For example, I need to add name key for each object inside the key manual. Likeways for other arrays of objects like nearest, auto. What would be the way to do this?
I tried to modify one key, and it changes the complete object. How could I avoid the reference thing here?

Do you mean something like this?
Say your data structure is called cars:
var cars = {
"status": 200,
"message": "Successful",
"data": {
"manual": [
{
...
Then you could add a property called name to the items under the property manual like
cars.data.manual = cars.data.manual.map(i => Object.assign({name: 'My ' + i.vendor}, i));
And similarly, to other items under different properties.
You can
console.log(cars);
afterwards to verify the result.

Related

Taking contents of an array of objects, and assigning them to a property on a JSON object

I want to take items from this array (the way I save things on the client)
[
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
]
And turn them into this format for how I save it server side
{ "todos": {
"-Mdawqllf_-BaW63gMMM": {
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800,
},
"-Mdawqllf_-BaW63gGHf": {
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000,
},
"-Mdawqllf_-BaW63gGHd": {
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000,
}
},
}
Basically i turn items into an array on the client to help with sorting and making use of arrays. But before sending it back need to put into the right format
Use .map() to loop over the array of objects to exctract the id property, so you can use it as the key of the new object.
Use Object.fromEntries() to create the new object from the array returned by .map().
const data = [
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
];
const todos = {
Todos: Object.fromEntries(data.map(obj => [obj.id, obj]))
};
console.log(todos);
#Barmar's solutions is nice.
For the sake of learning or others googling. You can also reduce the array to an object.
const todos = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
const items = {
todos: {
...data
}
};
Assume that data is the array of objects.
Use the spread operator to copy all the array objects from data array to the todos object at key todos.
One important thing to note that you can't assign more than one objects without array to a single object key. You definately have to use the array to maintain all the objects under the one key.
Avoid using the hardcode index. Always use the spread operator

parse JSON containing 2 arrays

My ajax call returns data like this:
{"result":[{"stats":{"min":{"caller_id.name":"Person1"},"count":"5"},"groupby_fields":[{"field":"caller_id","value":"ce4ddid73hes6e806d7070e21f961987"}]},{"stats":{"min":{"caller_id.name":"Person2"},"count":"2"},"groupby_fields":[{"field":"caller_id","value":"36ffbcfedbf9ba406d7070e21f96199c"}]},{"stats":{"min":{"caller_id.name":"Person3"},"count":"1"},"groupby_fields":[{"field":"caller_id","value":"714dd540dbefbe806d7070e21f96196a"}]},{"stats":{"min":{"caller_id.name":"Person4"},"count":"1"},"groupby_fields":[{"field":"caller_id","value":"ce4dd540dbefbe806d7070e21f961987"}]}]}
I then use var json = $.parseJSON(data); and get this (from the console log):
{result: Array(4)}
result:Array(4)
0:groupby_fields:Array(1)
0:{field: "caller_id", value: "ce4ddid73hes6e806d7070e21f961987"}
length:1
__proto__:Array(0)
stats:count:"5"
min:{caller_id.name: "Person1"}
__proto__:Object
__proto__:Object
1:{stats: {…}, groupby_fields: Array(1)}
2:{stats: {…}, groupby_fields: Array(1)}
3:{stats: {…}, groupby_fields: Array(1)}
length:4
__proto__:Array(0)
__proto__:Object
In previous calls I loop through the data to pull the values using something like this
var callerName = json[i]["caller_id.name"];
I'm not sure how to do it in this scenario.
I tried a few variations of the line above but didn't have any success.
I need to get the caller_id, count, and caller_id.name.
There are two types of structures in JSON: arrays [value1, value2] and objects {"key1":"value1", "key2":"value2"}.
In Javascript, you access:
array elements via array[index].
object properties via object.property or object['property']. The latter is required if the property name includes special characters.
You can chain these, so for instance you could write:
json.result[0].stats.min['caller_id.name']
json.result[0].stats.count
json.result[0].groupby_fields[0].field
json.result[0].groupby_fields[0].value
and so on.
This should't be difficult. Assuming the value of i is 0, here is the way by which you can get corresponding values:
let data = {
"result": [{
"stats": {
"min": {
"caller_id.name": "Person1"
},
"count": "5"
},
"groupby_fields": [{
"field": "caller_id",
"value": "ce4ddid73hes6e806d7070e21f961987"
}]
}, {
"stats": {
"min": {
"caller_id.name": "Person2"
},
"count": "2"
},
"groupby_fields": [{
"field": "caller_id",
"value": "36ffbcfedbf9ba406d7070e21f96199c"
}]
}, {
"stats": {
"min": {
"caller_id.name": "Person3"
},
"count": "1"
},
"groupby_fields": [{
"field": "caller_id",
"value": "714dd540dbefbe806d7070e21f96196a"
}]
}, {
"stats": {
"min": {
"caller_id.name": "Person4"
},
"count": "1"
},
"groupby_fields": [{
"field": "caller_id",
"value": "ce4dd540dbefbe806d7070e21f961987"
}]
}]
};
let i = 0;
console.log(data.result[i].stats.min['caller_id.name']);
console.log(data.result[i].stats.count);
console.log(data.result[i].groupby_fields[0].value);
I hope you can loop through data.result using a loop and provide specific values of i to the expressions.
To get the 'caller_id.name' key use
var json = {"result":[{"stats":{"min":{"caller_id.name":"Person1"},"count":"5"},"groupby_fields":[{"field":"caller_id","value":"ce4ddid73hes6e806d7070e21f961987"}]},{"stats":{"min":{"caller_id.name":"Person2"},"count":"2"},"groupby_fields":[{"field":"caller_id","value":"36ffbcfedbf9ba406d7070e21f96199c"}]},{"stats":{"min":{"caller_id.name":"Person3"},"count":"1"},"groupby_fields":[{"field":"caller_id","value":"714dd540dbefbe806d7070e21f96196a"}]},{"stats":{"min":{"caller_id.name":"Person4"},"count":"1"},"groupby_fields":[{"field":"caller_id","value":"ce4dd540dbefbe806d7070e21f961987"}]}]}
//json['result'][0]["stats"]["min"]['caller_id.name']
for (x in json['result']){ console.log(r['result'][x]["stats"]["min"]['caller_id.name'])}
result:
"Person1"
"Person2"
"Person3"
"Person4"

organize MongoDB document to manipulate the data better

I would need help making a data structure with mongodb.
I'm using JavaScript to manipulate data.
I would like to have a document structure of this type, but i'm not sure to do the right thing. I noticed that you tend to use the array also as a container of objects, and i also noticed that the mongodb update operators need a structure of this type. for example:
var mydoc = {
_id: ObjectId("5099803df3f4948bd2f98391"),
items:[ {"name": "name", "other": "other"},
{"name": "name", "other": "other"},
{"name": "name", "other": "other"}
]}
but organize data in this way do not like :) how i would like the document:
{
"_id": {
"$oid": "dfdsdsfdsff54sdf5ds"
},
"displayName": "name",
"userId": "h8566d9482gghffhtry565",
"info": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"statistics": {
"total": {
"stat1": 0,
"stat2": 0,
"stat3": 0,
"stat4": 0
},
"best": {
"distance": 0,
"stat1": 0,
"stat2": 0,
"stat3": 0,
"stat4": 0
},
"game": {
"one": 0,
"two": 0,
"three": 0,
"stat4": 0
}
},
"inventory": {
"item1": {
"property1": 0,
"property2": 0,
"property3": 0,
"property4": 0,
"level": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"skins": [
"skin1",
"skin2",
"skin3"
]
},
"item2": {
"property1": 0,
"property2": 0,
"property3": 0,
"property4": 0,
"level": {
"level": 1,
"currentExperience": 0,
"requiredExperience": 0,
"missingExperience": 0
},
"skins": [
"skin1",
"skin2",
"skin3"
]
}
},
"notifications": {},
"rewards": {}
}
Now i explain what the problems im having.
now if i have to change, for example, a property of a specific item that is inside inventory, i take the object "inventory" -> i look for the item i need and then i modify the property.
at the end of this, using an update operator "$set", i replace the "inventory" field.
This may be fine if you have very little data, but within that field there will be hundreds of "sub-field" and this seems like a useless waste resources.
Unfortunately, using $inc operator, i can not pass in any way "the path" of the property that i want to change.
could you help me?
here is what i do now
var userDoc = myCollection("userData");
var userData = userDoc.findOne({"userId": userId}, {items: 1, _id: 0});
//Other code
userData.inventory[itemName][propertyName] = //other code;
userDoc.update({"userId": userId},{"$set": userData});
Thanks,
Regards
If you want to update an embedded document, you can access it using dot notation.
For above document, to update "property1" of "item1" inside "inventory":
db.inventory.update({"userId":"h8566d9482gghffhtry565"},{"$set":{"inventory.item1.property1":"1"}})
the problem is that the "path" is dynamic, I do not know which item will be modified. is the user decide which properties of the items change, I found this solution:
var inc = {$inc: {}};
inc.$inc['inventory.'+itemName+"."+statName] = 1; // itemName and statName are variables created by user
userDoc.update({"userId": userId}, inc);

elasticsearch autosuggest returning tricky JSON

I'm running a node.js server that sends queries to an elasticsearch instance. Here is an example of the JSON returned by the query:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 9290,
"max_score": 0,
"hits": []
},
"suggest": {
"postSuggest": [
{
"text": "a",
"offset": 0,
"length": 1,
"options": [
{
"text": "Academic Librarian",
"score": 2
},
{
"text": "Able Seamen",
"score": 1
},
{
"text": "Academic Dean",
"score": 1
},
{
"text": "Academic Deans-Registrar",
"score": 1
},
{
"text": "Accessory Designer",
"score": 1
}
]
}
]
}
}
I need to create an array containing each job title as a string. I've run into this weird behavior that I can't figure out. Whenever I try to pull values out of the JSON, I can't go below options or everything comes back as undefined.
For example:
arr.push(results.suggest.postSuggest) will push just what you'd expect: all the stuff inside postSuggest.
arr.push(results.suggest.postSuggest.options) will come up as undefined even though I can see it when I run it without .options. This is also true for anything below .options.
I think it may be because .options is some sort of built-in function that acts on variables, so instead of seeing options as JSON and is instead trying to run a function on results.suggest.postSuggest
arr.push(results.suggest.postSuggest.options)
postSuggest is an array of object.options inside postSuggest is also array of object. So first you need to get postSuggest by postSuggest[0] and then
postSuggest[0].options to get array of options
This below snippet can be usefule
var myObj = {..}
// used jquery just to demonstrate postSuggest is an Array
console.log($.isArray(myObj.suggest.postSuggest)) //return true
var getPostSuggest =myObj.suggest.postSuggest //Array of object
var getOptions = getPostSuggest[0].options; // 0 since it contain only one element
console.log(getOptions.length) ; // 5 , contain 5 objects
getOptions.forEach(function(item){
document.write("<pre>Score is "+ item.score + " Text</pre>")
})
Jsfiddle

How do I chain "SelectMany" calls with linqjs (or flatten JSON)

Using linq.js how can I chain two SelectMany calls together.
Given the following JSON structure:
[
{
"UpFrontCost": "29.95",
"Currency": "USDAUD",
"FittingDate": "2013-07-08 06:30:16Z",
"Widgets": [
{
"ID": 3,
"Name": "Test1"
},
{
"ID": 4,
"Name": "Test19"
},
{
"ID": 6,
"Name": "Test8"
}
]
},
{
"UpFrontCost": "29.95",
"Currency": "USDAUD",
"FittingDate": "2013-07-08 06:30:16Z",
"Widgets": [
{
"ID": 67,
"Name": "Test1"
},
{
"ID": 99,
"Name": "Test19"
},
{
"ID": 34,
"Name": "Test8"
}
]
}
]
I would like a list of all the "Widgets" (in this example a list of 6 widgets).
You don't need to really chain anything. Your root object is an array, you just want to select each widget for each object in that array.
var query = Enumerable.From(jsonObject)
.SelectMany("$.Widgets") // Select each widget found in the Widgets property
.ToArray();
To flatten that array of widgets attaching each property of the parent object to the result, there's a couple of ways you could do it. You can use a nested query using the function syntax.
var query = Enumerable.From(jsonObject)
.SelectMany(function (item) {
return Enumerable.From(item.Widgets)
.Select(function (widget) {
return {
ID: widget.ID,
Name: widget.Name,
UpFrontCost: item.UpFrontCost,
Currency: item.Currency,
FittingDate: item.FittingDate
};
});
})
.ToArray();
Or using the lambda string syntax:
var query = Enumerable.From(items)
.SelectMany("$.Widgets",
// argument 1 ($) - the parent object
// argument 2 ($$) - the selected object (a widget)
"{ ID: $$.ID, Name: $$.Name, UpFrontCost: $.UpFrontCost, Currency: $.Currency, FittingDate: $.FittingDate }"
)
.ToArray();

Categories

Resources