NodeJS/AngularJS - Reading Array of Objects from JSON - javascript

I've got an issue reading a nested array from JSON(BSON from MongoHQ) using Node and Angular.
JSON snippet: http://pastie.org/9305682. Specifically look for the edges array.
Mongoose model: http://pastie.org/9305685
Basically I call the character from the DB and then attempt to log it to the console with
console.log(char); before sending it back to the angular call with res.json(char); 'char' is the returned character from the databased saved as my mongoose model.
Attempting to log the character to the console. I get everything looking normal except for the portions with the nested "effects" arrays. Anywhere they show up I receive the following:
edges:
[ { name: 'Super Hacker', notes: '', effects: [Object] },
{ name: 'Witty', notes: '', effects: [Object] },
{ name: 'Attractive', notes: '', effects: [Object] },
{ name: 'Encyclopedic Memory',
notes: 'Prereq: d8 Smarts',
effects: [Object] },
{ name: 'Daywalker', notes: '', effects: [Object] },
{ name: 'Tough', notes: '', effects: [Object] } ],
From here if I try to call it with:
From NodeJS - console.log(char[0].edges[0].effects[0].type); - Returns undefined.
From Angular View - {{cur_char.edges[0].effects[0].type}} - Displays nothing.
Thanks in advance for the help. Let me know if I can provide more in.

I think what you're asking is how to see more depth to the object in the console output. You can use util.inspect to print out more information:
console.log(util.inspect(char, { depth: 5 }));
By default util.inspect only goes to a depth of 2 which explains why you can only see the contents of the array (1) and the primitive properties of each element in the array (2).
See: http://nodejs.org/api/util.html#util_util_inspect_object_options

Related

Check if a nested property has an object that partially matches a target in expect

I have an object like this:
> const expect = require('chai').expect
> r = { loadedElementData: { userIdRecord: { name: 'Chiara', surname: 'Fabbietti', id: 1 } }, resolvedIdParamsValues: { users: 1 }, resolvedListFilter: {}, totalLoads: 1 }
I can check if an object with specific contents is somewhere deep in r -- this doesn't throw:
> expect(r).to.have.nested.deep.property('loadedElementData.userIdRecord', { name: "Chiara", surname: "Fabbietti", id: 1 })
However, I want to check for partial objects. So, I would like something like this to pass even though the comparison object is a partial match:
> expect(r).to.have.nested.deep.property('loadedElementData.userIdRecord', { id: 1, name: 'Chiara' })
This obviously won't work, since it will check for the object's deep equality.
This in theory should work:
expect(r).to.nested.include({'loadedElementData.userIdRecord': { id: 1, name: 'Chiara' } })
But doesn't.
This should REALLY work:
expect(r).to.deep.nested.include({ 'loadedElementData.userIdRecord': { id: 1, name: 'Chiara' } })
But doesn't.
I can make it work checking ONE property (only 'id'):
expect(r).to.nested.include({ 'loadedElementData.userIdRecord.id': 1})
But I am limited to check for id, and can't check for name too at the same time.
I can do this in 2 steps:
> expect(r).to.include.nested.property('loadedElementData.userIdRecord')
> expect(r.loadedElementData.userIdRecord).to.include({ id: 1 })
But this is a two step process -- can I do it in one step?
If you check their Github issues, maintainers acknowledge that the nested inclusion of an object subset is not working since 2020. Reference: chai Github
This is the line where Chai decides if doing a deep equality or a strict equality when comparing two objects: https://github.com/chaijs/chai/blob/a8359d3d15779a23a7957a4c52539d48de2763e0/lib/chai/core/assertions.js#L1892.
_.eql is a reference to Chai's deep equal own library implementation.
In the deep-eql library the flow will reach to this function that does loose equality comparisons but not partial ones.

Printing Object doesnt contain all keys

Im completely lost. This is some test code I use to print a specific key of an object, then im printing the entire object.
console.log(docs[0].mc_ign);
console.log(docs[0]);
Now this is the output I see on the console:
The__TxT
{
id: 0,
status: 1,
testing: false,
_id: 5dbc17eb20b3a8594d569570,
timestamp: 2019-11-01T11:32:59.380Z,
mc_uuid: 'dac89e44d1024f3b810478ed62d209a1',
discord_id: '653029505457586176',
email_address: 'gut97930#eveav.com',
country: 'Germany',
birth_month: 3,
birth_year: 1943,
about_me: 'about me text',
motivation: 'motivation text',
build_images: '',
publish_about_me: true,
publish_age: false,
publish_country: true,
__v: 0
}
Where is the mc_ign key?
The object itself comes from mongoose, the missing key is added by me after the fact:
docs[i].mc_ign = mc_ign;
I tried logging the entire object before and after I add the key and assign the value. They are both the same.
What am I missing? Why can I read the value out, but cant see it?
It is mongoose document object. To achieve what you want do the following.
docs[0] = docs[0].toObject();
docs[0].mc_ign = "stuff";
console.log(docs[0])
.toObject() convert it to plain JS object.

In what form to keep a chat list and their messages in client side

I have 2 options for storing the received data
1.
[
{
chatId: 'chatId1',
author: 'authorId1',
members: [],
messages: []
},
{
chatId: 'chatId2',
author: 'authorId2',
members: [],
messages: []
},
...
]
2.
{
'chatId1': {
author: 'authorId1',
members: [],
messages: []
},
'chatId2': {
author: 'authorId2',
members: [],
messages: []
},
...
}
In the first option, to add a message in chat with the chatId2 ID, I have to loop and find the missing chat, but in the second option, I can get the chatId2 property of an object.
What form do you recommend?
P.S. Sorry for my English. Thanks ;)
It depends on what you need to do, size of the data, requirements, etc.
You can easily combine these options by keeping the id field and looping though values if needed. But depending on your tasks you may also need to add additional sorting then.

Native JavaScript Way to Walk up Document Tree When Comparing Objects

I have done some work to do a deep comparison (via Underscore and diff) between two objects (actually a pre-save and post-save version of the same document) in order to isolate the section that is different after a save. Take this document structure as an example:
{
_id: 4d39fe8b23dac43194a7f571,
name: {
first: "Jane",
last: "Smith"
}
services: [
{
service: "typeOne",
history: [
{ _id: 121,
completed: true,
title: "rookie"
},
{ _id: 122,
completed: false,
title: "novice"
}
]
},
{
service: "typeTwo",
history: [
{ _id: 135,
completed: true,
title: "rookie"
},
{ _id: 136,
completed: false,
title: "novice"
}
]
}
]
}
If a new element is added to the history array I'm able to successfully parse out that change.
However, in addition to pulling out this changed section, I also want to be able to effectively walk up from history in order to find the value for service, because I also need to know which of the two services array elements actually changed. Is there a way I can do this with native es6 JavaScript?
If not, is there a library I can use to determine this? Right now I'm able to get the value for "service" via indexing:
if (diff.path[1] === 0) {
targetService = "typeOne";
} else if (diff.path[1] === 1) {
targetService = "typeTwo";
} else if (diff.path[1] === 2) {
targetService = "typeThree";
}
But from my understanding this isn't full proof, because there's no guarantee the order of elements within "services" couldn't change at some point. I suppose this indexing method could work if I could enforce the ordering of the elements within the services array. I'm just not sure if there's a way to do that (open to suggestions if it is possible).
deep-diff gives you the path to this change, something like this:
{
kind: 'N',
path: ['services', 1, 'history'],
// ... other properties
}
You can use this path to track the changed object:
tree.services[changes.path[1]].service // 'typeTwo'

Why can't I see all JS object properties on a Mongoose document?

I'm writing a route in Express (Node.js) in which i pull some data from mongoose. Let's say that at some some point I need to compare if employee._id is in array of bad employees id::
let employees = await EmployeeModel.find().exec();
employees.forEach(function (employee) {
if (arrayOfBadEmployees.indexOf(employee._id) !== -1) {
employee.isBad = true;
}
});
console.log(employees);
console.log(employees[0].isBad);
and here's my output:
[ { __v: 0, name: 'Employee X', _id: 1 },
{ __v: 0, name: 'Employee Y', _id: 3 },
{ __v: 0, name: 'Employee Z', _id: 5 } ]
true
So when I can't see 'isBad' property when I console.log the whole array/object, but this property is still there? When i check with propertyIsEnumerable('isBad') it says true.
Mongoose, by default, returns an instance of MongooseDocument, which doesn't expose your data directly and adds convenience methods like populate or save
You can use the lean option to get raw objects instead.
MongooseDocument also exposes a toObject function if you need to get editable documents.

Categories