How to get the name of the most "root" key? - javascript

I have a js object in NodeJs application:
> req.body
{ my_root_key: { some_key2: [ [Object] ], some_key3: [ [Object] ] } }
How can I obtain the name of the most base key, in this case "my_root_key"?

Try this:
var data = { my_root_key: { some_key2: [ [Object] ], some_key3: [ [Object] ] } }
console.log(Object.keys(data)[0]);

Related

mongoDB project array element after filter

I have the following (simplified) aggregation:
Model.aggregate([
{
$lookup: {
from: 'orders',
localField: '_id',
foreignField: 'customer',
as: 'orders',
},
},
{
$project: {
openOrders: {
$filter: {
input: '$orders',
as: 'order',
cond: { $eq: ['$$order.status', 'open'] },
},
},
},
},
])
which returns the following:
{
_id: ...,
openOrders: [
[Object], [Object]
],
}
Those [Object]'s are simply the returned objects, persisted in the database, with all their fields.
I don't find a way to project/filter out those objects' fields and instead return only their _id's:
{
_id: ...,
openOrders: [
_id: ...,
_id: ....
],
}
EDIT: I'd rather prefer the following expected output:
{
_id: ...,
openOrders: [
{ _id: ... },
{ _id: ... }
],
}
I tried adding a new $project stage at various points of the aggregation with no success. Can someone help me?
You should add a $project stage like below:
{
$project: {
openOrders: 'openOrders._id'
}
}
This will give the output like:
{
_id: ...,
openOrders: [
_id1,
_id2,
...
],
}
instead of
{
_id: ...,
openOrders: [
_id: ...,
_id: ....
],
}
I suggest this type of querying because, if you actually see openOrders, it's just the array of _ids, so adding only one _id field inside the array doesn't make sence.
If you still want the output to be like the array of object, then you can use the below:
{
$project: {
'openOrders._id': 1
}
}
As you need an array of _id's like this
openOrders: [ _id: ..., _id: .... ]
but not an array of _id's in objects :
openOrders: [ {_id: ...}, {_id: ....} ]
You need to use $reduce instead of $filter :
Try below query :
db.collection.aggregate([
{
$project: {
openOrders: {
$reduce: {
input: "$orders", // Same like `$filter` use reduce to iterate on array
initialValue: [], // consider an initial value
in: { // If condition is met, push value to array else return holding array as is.
$cond: [ { $eq: [ "$$this.status", "open" ] },
{ $concatArrays: [ "$$value", [ "$$this._id" ] ] },
"$$value"
]
}
}
}
}
}
])
Test : mongoplayground
Note : In javaScript - if you're printing a JSON with objects, you need to print it with JSON.stringify(yourJSON) - which makes it a string, So that you don't see [Object], [Object] in console rather you would see actual objects.
Update :
If you need an array of objects with _id field just add another $project stage at the end, but I would highly suggest to use $reduce and get an array for your scenario :
{ $project: { "openOrders._id": 1 } } // which would just extract `_id` fields in each objects
Test : mongoplayground

js add object to object with $or and get [object]

I try to generate an object with {$or: [{object1}, {object2},...]} to fire a query to mongo, but I always get [object] after assigning to $or. Can somebody help me and tell me what I´m doing wrong. I tried it with creating an own array for the $or[], with a for-loop and so on - always the same. Some ideas?
if(req.body.sicDiv) {
co_sicDiv = {
$in: sicDiv.split(',')
};
query = Object.assign({co_sicDiv: co_sicDiv}, query);
//works fine, I get: { co_sicDiv: { '$in': [ 'C' ] }
}
if(req.body.sicMajor) {
if (sicDiv){
co_sicMaj = {
$in: sicMaj.split(',')
};
console.log('co_sicMaj: ', co_sicMaj);
sicMajO =Object.assign(
{'co_sicDiv': co_sicDiv},
{'co_sicMaj' : co_sicMaj}
);
console.log('SicMajO: ', sicMajO);
//Works fine, I get: SicMajO: { co_sicDiv: { '$in': [ 'C' ] }, co_sicMaj: { '$in': [ '15', '16' ] } }
sicMajOR =Object.assign({$or: [
{'co_sicDiv': co_sicDiv},
{'co_sicMaj' : co_sicMaj}
]}
);
console.log('SicMajOR: ', sicMajOR);
//Doesn´t work, I get: SicMajOR: { '$or': [ { co_sicDiv: [Object] }, { co_sicMaj: [Object] } ] }

How to I get the values of the keys in this javascript object inside the arrays?

I need the value for the key country_code and language_code.
I have tried
sourceLanguageArray[0].$.country_code;
sourceLanguageArray[0].$.language_code;
I get the error:
console.log(sourceLanguageArray[0].$.country_code);
^
ReferenceError: sourceLanguageArray is not defined
This is how the code and console logs of the data structure looks like:
source_language (includes country_code and language_code)
const sourceLanguageArray = _.map(ontomlClass, 'source_language');
console.log(sourceLanguageArray);
// => [ [ { '$': [Object] } ], [ { '$': [Object] } ],[ { '$': [Object] } ] ]
// => [ { '$': [Object] } ]
console.log(sourceLanguageArray[0]);
// => [ { '$': { country_code: 'US', language_code: 'en' } } ]
var sourceLanguageArray = [[ { '$': { country_code: 'US', language_code: 'en' } } ]];
console.log("sourceLanguageArray[0]:", sourceLanguageArray[0]);
console.log("country code:", sourceLanguageArray[0][0].$.country_code);
console.log("language code:", sourceLanguageArray[0][0].$.language_code);
try this:
sourceLanguageArray.forEach(function(item){
console.log(item[0]['$'][country_code]);
console.log(item[0]['$'][language_code]);
})

XML Attribute not working in Node.js xml2js

I'm trying to parse XML with Node.js and xml2js. In the documentation is says that $ is the character to access attributes. It doesn't seem to be working in my case.
The object result.ApiResponse.CommandResponse works fine. But anything I put afterwards is undefined.
Here's my code, it says $ is undefined :
var xml2js = require('xml2js');
var util = require('util');
var parser = new xml2js.Parser();
var xml = '<ApiResponse Status="OK"><Errors/><Warnings/><RequestedCommand>namecheap.domains.check</RequestedCommand><CommandResponse Type="namecheap.domains.check"><DomainCheckResult Domain="us.xyz" Available="true" ErrorNo="0" Description="" IsPremiumName="true" PremiumRegistrationPrice="13000.0000" PremiumRenewalPrice="13000.0000" PremiumRestorePrice="65.0000" PremiumTransferPrice="13000.0000" IcannFee="0.0000" EapFee="0.0000"/></CommandResponse><Server>PHX01APIEXT01</Server><GMTTimeDifference>--5:00</GMTTimeDifference><ExecutionTime>4.516</ExecutionTime></ApiResponse>';
parser.parseString(xml, function (err, result) {
console.log(util.inspect(result.ApiResponse.CommandResponse.DomainCheckResult.$.Available, false, null))
});
Here's the console.log(result):
{ ApiResponse:
{ '$': { Status: 'OK' },
Errors: [ '' ],
Warnings: [ '' ],
RequestedCommand: [ 'namecheap.domains.check' ],
CommandResponse:
[ { '$': { Type: 'namecheap.domains.check' },
DomainCheckResult:
[ { '$':
{ Domain: 'us.xyz',
Available: 'true',
ErrorNo: '0',
Description: '',
IsPremiumName: 'true',
PremiumRegistrationPrice: '13000.0000',
PremiumRenewalPrice: '13000.0000',
PremiumRestorePrice: '65.0000',
PremiumTransferPrice: '13000.0000',
IcannFee: '0.0000',
EapFee: '0.0000' } } ] } ],
Server: [ 'PHX01APIEXT01' ],
GMTTimeDifference: [ '--5:00' ],
ExecutionTime: [ '4.516' ] } }
It looks like CommandResponse and DomainCheckResult are actually arrays, so you need to access their first elements using [0] before digging deeper into your data.
console.log(util.inspect(
result.ApiResponse.CommandResponse[0].DomainCheckResult[0].$.Available,
false, null
))

NodeJS module - populated arrays turning into empty objects. Why?

I have a module which exports a config object:
module.exports = {
music : {
catalog : {
mysql : {
requiredFields : {
foo : [1,2,3],
trackQuery : [
{
table : 'tracks',
alias : 't',
foo : [1,2,3],
fields : [
'id',
'name',
'duration'
]
},
{
table : 'artists',
alias : 'a',
fields : [
'id',
'name'
]
}
]
}
}
}
}
}
The fields arrays are turning into empty objects at runtime.
I'm confirming like this:
var conf = require('musicConfig');
console.log ("requiredFields = %j", conf.music.catalog.mysql.requiredFields);
...which outputs this:
requiredFields = ["foo":[1,2,3],"trackQuery":[{"table":"tracks","alias":"t","foo":{},"fields":{}},{"table":"artists","alias":"a","fields":{}}]]
As you can see:
conf.music.catalog.mysql.requiredFields.foo // [1,2,3]
conf.music.catalog.mysql.requiredFields.trackQuery[0].foo // {} <-- WTF
conf.music.catalog.mysql.requiredFields.trackQuery[0].table // "tracks"
Any idea what's going on? Yes, I can move the fields array to a higher level namespace and it will work - one step up actually. If I put it directly under requiredFields it will stay populated, but that's not an ideal solution.
I've confirmed here that it's not an ECMAScript bug and it's not my object structure, because it works as expected.
I'm running Node 0.10.3 on Ubuntu with these dependencies:
"dependencies" : {
"express" : "3.1.0",
"redis" : "0.8.2",
"jade" : "0.28.2",
"mysql" : "2.0.0-alpha7",
"mongodb" : "*",
"config" : "0.4.22"
}
I thought it might be that config module, but even when I bypass it the issue remains.
UPDATEHere is the output from: console.log(util.inspect(config.music.catalog.mysql.requiredFields.trackQuery[0], { showHidden: true, depth: null }));
-- though it doesn't really help much. I'm looking into more helpful flags, open to suggestions.
{ table: [Getter/Setter],
alias: [Getter/Setter],
foo: [Getter/Setter],
fields: [Getter/Setter],
[__watchers]:
{ table:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
alias:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
foo:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ],
fields:
[ { [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } },
[length]: 1 ] },
[__propertyValues]:
{ table: [ 'tracks', [length]: 1 ],
alias: [ 't', [length]: 1 ],
foo: [ { [__watchers]: {}, [__propertyValues]: {} }, [length]: 1 ],
fields: [ { [__watchers]: {}, [__propertyValues]: {} }, [length]: 1 ] } }
I can reproduce the problems when the file is read using the config module, so I don't think you're bypassing it correctly.
Also, when I increase DEFAULT_CLONE_DEPTH in config/lib/config.js (it doesn't seem to be configurable from the outside, but I'm not very familiar with it), it works:
> console.log(conf.music.catalog.mysql.requiredFields.trackQuery[0].foo)
[ [Getter/Setter], [Getter/Setter], [Getter/Setter] ]

Categories

Resources