I am querying my mongodb using mongoose, but i don't understand why the returned sub docs are just of type Object, instead of JSON.
Using
hero.find({} ,{'deck' : {$elemMatch:{name:'Guard Tower'}}}, function(err, tower) {
console.log(tower);
}
returns
[ { _id: 507ac406ba6ecb1316000001,
deck:
[ { name: 'Guard Tower',
description: 'This tower shoots stuff.',
cost: 13,
sellValue: 7,
radius: 180,
speed: 40,
dmg_min: 0,
dmg_max: 0,
actual_height: 40,
sprite: 'guardtower_red.png',
anim: [Object],
size: [Object],
projectile: [Object],
upgrade: [Object] } ] } ]
Subdocument like anim, size, projectile, upgrade, is Object, i need the information nested, how can i get the information? Without making another query?
The all docs and subdocs are objects in JavaScript. It's just that console.log uses the default depth of 2 when calling util.inspect to format your document for output. You can output all levels of the document by calling util.inspect yourself:
var util = require('util');
hero.find({} ,{'deck' : {$elemMatch:{name:'Guard Tower'}}}, function(err, tower) {
console.log(util.inspect(tower, false, null));
});
JohnnyHK is correct however a simpler approach if you just want to log out JSON would be
console.log(tower.toJSON());
You can see my comment to Rodrigo about why this works.
Making the query on Mongoose using find() as you did will return Mongoose Documents (not JSON). You can use the lean() method to return POJOs:
hero
.find({} ,{'deck' : {$elemMatch:{name:'Guard Tower'}}})
.lean()
.exec(function(err, tower) {
//tower is a JSON here
console.log(tower);
});
But what JohnnyHK said it's true about the console log, it will only show nested documents as [Object].
UPDATE: Beware that using .lean() will return objects and any virtual fields or special getters you might have will be ignored.
Related
just a general question - fairly new to js. I have a script that converts a csv to json. I'd like to test the json output without writing it to a file using Jest. Is that possible with Jest's expect?
As in jest documentation
Use .toMatchObject to check that a JavaScript object matches a subset
of the properties of an object. It will match received objects with
properties that are not in the expected object.
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
},
};
const desiredHouse = {
bath: true,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
wallColor: expect.stringMatching(/white|yellow/),
},
};
expect(houseForSale).toMatchObject(desiredHouse);
looking for some help here.
I have a basic postgres select statement that simply returns a JSONb column.
******* Edit to add SQL query ************
anpool.query(`SELECT data as test
FROM appanalytics
WHERE to_date(data->>'dateTime', 'MM/DD/YYYY')
BETWEEN $3
AND $4
AND cid=$1 AND aid=$2`,[req.session.cID,req.session.AccountID,endDate,startDate]).then(analytics =>{
//This returns an array of objects, each object in the array
// is wrapped in the column name as shown above
console.log(analytics)
});
Now this works fine however each object in the array is wrapped in the table name
[
{
test: {
ip: '10.10.10.10',
atID: 0,
uuID: '084B98DE-6D89-490E-8238-E25DDC8E5C04',
itemID: '0',
timeEnd: '2021-07-28T13:40:16.788Z',
actionID: 'speakerMainDetail',
dateTime: '07/28/2021',
location: [Object],
timeStart: '2021-07-27T12:54:21.284Z',
deviceType: 'web'
}
}
]
So, in this response you can see, the object is nested in 'test' I need it to be the top level, so each response object is not nested in test, any ideas on how that might be possible? Using nodeJS and pg npm.
Thanks
You get back an array of rows, each an object with the columns you were selecting. There's not really anything you can or should do against that - notice you cannot use ip, atID etc as column names since (presumably) these are dynamic. You can do
anpool.query(
`SELECT data as test
FROM appanalytics
WHERE to_date(data->>'dateTime', 'MM/DD/YYYY')
BETWEEN $3
AND $4
AND cid=$1 AND aid=$2`,
[req.session.cID,req.session.AccountID,endDate,startDate]
).then(result => {
const analytics = result.rows.map(row => row.test);
console.log(analytics);
});
You can extract it like this:
const res = [
{
test: {
ip: '10.10.10.10',
atID: 0,
uuID: '084B98DE-6D89-490E-8238-E25DDC8E5C04',
itemID: '0',
timeEnd: '2021-07-28T13:40:16.788Z',
actionID: 'speakerMainDetail',
dateTime: '07/28/2021',
location: [Object],
timeStart: '2021-07-27T12:54:21.284Z',
deviceType: 'web'
}
}
];
const { test } = res[0];
console.log(test);
I am using Redis in my backend to scale subscriptions. I am using this library to implement redis on top of my javascript code. And using mongoose for the models.
During a redis publish, I have to stringify the objects that I get from mongoose. I parse them on the subscribing end and it all works well until there's a nested object in the object that needs to be stringify-ed.
So if my object is this:
{ subtitle: '',
description: '',
checklists:
[ { _id: 5cee450c0fa29d0b54275da0, items: [] },
{ _id: 5cee455c0c31785b0875e09d, items: [] },
{ _id: 5cee47dc6d32e72c6411ce2d, items: [] } ],
attachments: [],
labels: [],
_id: 5ced1af26547233798f943f6,
title: 'asfasf',
box: 5cece1c3e6c3c13ff098658d,
workflow: 5cece1cbe6c3c13ff0986591,
}
I receive:
{ cardUpdated:
{
subtitle: '',
description: '',
checklists: [ [Object], [Object], [Object] ],
attachments: [],
labels: [],
_id: '5ced1af26547233798f943f6',
title: 'asfasf',
box: '5cece1c3e6c3c13ff098658d',
workflow: '5cece1cbe6c3c13ff0986591',
}
}
When I publish I use the following line:
pub.publish(types.CARD_UPDATED,
JSON.stringify(
{ cardUpdated: await getUpdatedCardStats(checklist.card) },
));
Note: I know that I am wrapping the argument for stringify in {} and without it the nested objects would not be ignored, but I need to do that because I need the key property name on the subscription end i.e. I am using this publish command with different key names at several places.
Is there a way to about this to get the nested objects stringify-ed?
EDIT: Turns out, I was getting the proper full object as a string on the subscribing end of Redis, but it was actually JSON.parse() that was the culprit. After parsing, it completely ignores the nested objects. Is there anyway to avoid this?
Try:
const value = JSON.stringify({
cardUpdated: await getUpdatedCardStats(checklist.card)
});
pub.publish(types.CARD_UPDATED, value);
This is not a valid JS object:
{ _id: 5cee450c0fa29d0b54275da0, items: [] }
I think it's the output of .toString() of an object of type {_id: ObjectId, items: any[], with ObjectId defined here. In any case, the JSONification of this object is not trivial and that is why JSON.stringify simply outputs [Object].
To bypass this limitation, you might implement a custom function to transform your object into one that can be trivially JSONified, possibly with the help of ObjectId.toString().
I have a problem with logging out the contents of an array inside an object. The actual object looks like this
var stuff = { accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: ['new item1', 'new item2'] },
messageId: 'xxxxxxxxxxxxx' } }
The console.log shows the items of the first array fine but the second array is being output as [Object].
{ accepted: [ 'item1', 'item2' ],
rejected: [],
response: 'Foo',
envelope: { from: 'The sender', to: [Object] },
messageId: 'xxxxxxxxxxxxx' } }
What is happening here and how can I get the items of the second array to show when I console.log. Thanks for any help!
UPDATE
Sorry, I forgot to add that I am working exclusively in Node.js so it's a server side log that needs to display the object exactly as it's received from a callback with a straight console.log, ie. no further stringify-ing.
I also just tried creating another random object with a similar structure like this.
var objText = {
fun: {
stuff: 'Some stuff',
list: ['this', 'it', 'takes']
}
};
The console.log for the above is:
{ fun: { stuff: 'Some stuff', list: [ 'this', 'it', 'takes' ] } }
This appears to be the same structure to me and yet the console.log works fine so it seems to be perfectly possible in Node to log arrays content even when it's embedded inside and an object inside an outer object.
It looks like this is an old topic, anyway
I've faced the same issue, embedded array printed as [Array].
It is because of console.log in the node.js uses util.inspect for print, the default depth is 2.
So, to print something which is deeper than 2 followings can be used:
const util = require('util')
console.log(util.inspect(errors, true, 10))
This is the default way for some browser and implementations of showing too complex or deep objects/arrays with console.log. An alternative is to use JSON.stringify with console.log:
var stuff = {
accepted: ['item1', 'item2'],
rejected: [],
response: 'Foo',
envelope: {
from: 'The sender',
to: ['new item1', 'new item2']
},
messageId: 'xxxxxxxxxxxxx'
}
console.log(JSON.stringify(stuff, null, 4));
EDIT:
Another alternative is to use console.dir in case you have a too complex or recursive object, see https://stackoverflow.com/a/27534731/6051261
Try it with: console.log(JSON.stringify(variable))
If you like Chrome devtools, that folds your json objects and let you observe a lot of things, you can use the --inspect flag:
node --inspect index.js
The console will then give you an URL and you just have to copy paste in Google Chrome to enjoy Google Chrome console.
More information on this link
I've looked around quite a bit concerning this error, it seems that Mongo won't accept a . or a $ in an update, yet I still get this error
{ [MongoError: not okForStorage]
name: 'MongoError',
err: 'not okForStorage',
code: 12527,
n: 0,
connectionId: 18,
ok: 1 }
This is the object I'm updating:
{
status: "open",
type: "item",
parentId: "4fa13ba2d327ca052d000003",
_id: "4fa13bd6d327ca052d000012",
properties: {
titleInfo: [
{ title: "some item" }
]
}
}
And I'm updating it to:
{
fedoraId: 'aFedoraLib:438',
status: "closed",
type: "item",
parentId: "4fa13ba2d327ca052d000003",
_id: "4fa13bd6d327ca052d000012",
properties: {
titleInfo: [
{ title: "some item" }
]
}
}
Another possible cause I just ran into: storing an object which has periods in the string keys.
So for people getting the same error:
It's due to the fact that I was including the _id, which Mongo doesn't like apparently
I ran into this error when trying to save a JSON structure with this key-value pair (coming straight out of an AngularJS app):
"$$hashKey":"021"
Removing just that key fixed the problem. For others using Angular, it looks like calling Angular's built-in angular.toJson client-side eliminates the $$hashkey keys. From their forums:
$scope.ngObjFixHack = function(ngObj) {
var output;
output = angular.toJson(ngObj);
output = angular.fromJson(output);
return output;
}