How to loop over rows after .fetchAll Bookshelf js + knex js? - javascript

I have a MySQL Database which I need to query from node.js
I am using bookshelf and knex for this.
I want to get the contents of a table - I have defined a table in my model.js file. I am attempting the query like this:
//select * from completedSentences;
Model.CompletedSentences.fetchAll().then(function (resData) {
console.log(resData)
})
I would like to know how to loop over resData because it should be multiple rows.
The output of the console looks like this: I dont see a list of rows I can loop over.. What am i missing?
CollectionBase {
model:
{ [Function]
NotFoundError: [Function: ErrorCtor],
NoRowsUpdatedError: [Function: ErrorCtor],
NoRowsDeletedError: [Function: ErrorCtor] },
length: 1,
models:
[ ModelBase {
attributes: [Object],
_previousAttributes: [Object],
changed: {},
relations: {},
cid: 'c4',
id: 1 } ],
_byId:
{ '1':
ModelBase {
attributes: [Object],
_previousAttributes: [Object],
changed: {},
relations: {},
cid: 'c4',
id: 1 },
c4:
ModelBase {
attributes: [Object],
_previousAttributes: [Object],
changed: {},
relations: {},
cid: 'c4',
id: 1 } },
_knex: null,
_events: {},
_eventsCount: 0 }

I found the answer (the documentation is very cryptic, hope this helps others)
new Model.CompletedSentences().fetchAll().then(function (resData) {
_.each(resData.models, function (model) { //I am looping over models using underscore, you can use any loop
console.log(model.attributes)
})
})

Model.CompletedSentences.fetchAll().then(function (resData) {
console.log(resData.serialize())
})
output is in json format
http://bookshelfjs.org/#Model-instance-serialize

The Collection class has a set of lodash methods for this.
You can use collection.forEach this way:
new Model.CompletedSentences().fetchAll().then(function (completedSentences) {
completedSentences.forEach(function (model) {
console.log(model.attributes)
})
})
Check out the docs, there are many other useful methods for Collection.

If you dont want to use lodash, you can do this:
new Model.CompletedSentences().fetchAll().then(function (resData) {
resData.models.forEach( function (model) {
console.log(model.get('attribute');
console.log(model.related('sth').get('attribute');
})
})

simply just console with it attributes.
console.log(resData.attributes);
you will get results Objects vise.

Answer is simple, try this
console.log(resData.toJSON())

Related

Recursive in typescript

Please help me write a method for finding child objects. The method receives the name of the object and an array of all possible objects. I need to find an object by the input name in this spike, then see what child objects it has, then go through each object in the same way. Thus, you need to find all the children throughout the cascade. The resulting file is this.ArchiveObject[]. The method I wrote "findChildObjects" goes to infinity and doesn't work correctly.
public async execute(): Promise<void> {
const templateExecutionSteps = await this.getTemplateExecutionSteps();
// Get global describe
const globalDescribe = await SfDescribe.objects(this.auth);
await this.backup.sobjectKeyPrefix(globalDescribe);
// Get names of user-selected objects
const objectsName = [...templateExecutionSteps.keys()].map(objectName => {
const describeObject = globalDescribe.sobjects.find(describeObj => describeObj.name === objectName);
if (!describeObject) throw new Error(`Object ${objectName} not found`);
if (!describeObject.queryable) throw new Error(`Object ${objectName} not queryable`);
return describeObject;
});
// Get names of all objects from org
const globalDescribeNames: string[] = [];
globalDescribe.sobjects.forEach(obj => globalDescribeNames.push(obj.name));
// Get global describe for all objects from org
const describeAllObjects = await SfCompositeUtils.describeObjects(this.auth, globalDescribeNames, true);
// Push global describe for all objects result in map
const globalDescribeMap: Map<string, SFDescribeObjects> = new Map();
describeAllObjects.forEach(objectDescribe => globalDescribeMap.set(objectDescribe.name, objectDescribe));
this.objectsArray = [];
objectsName.forEach(object => {
const allObjects = this.findChildObjects(object.name, globalDescribeMap);
});
}
public findChildObjects(selectedObject: string, globalDescribeMap: Map<string, SFDescribeObjects>): any {
const currentObject: ArchiveObject = {};
console.log(globalDescribeMap);
globalDescribeMap.get(selectedObject).childRelationships.forEach(object => {
if (
this.objectsArray.find(item => item.objectName === object.childSObject && item.referenceField === object.field)
) {
return;
}
currentObject.referenceTo = selectedObject;
currentObject.objectName = object.childSObject;
currentObject.referenceField = object.field;
if (object.cascadeDelete || object.restrictedDelete) {
currentObject.isDelete = true;
this.objectsArray.push(currentObject);
const result = this.findChildObjects(object.childSObject, globalDescribeMap);
this.objectsArray.push(...result);
} else {
currentObject.isDelete = false;
this.objectsArray.push(currentObject);
}
});
return this.objectsArray;
}
export interface ArchiveObject {objectName?: string; referenceField?: string; referenceTo?: string; isDelete?: boolean;}
Here is the globalDescribeMap structure:
'DashboardFeed' => {
actionOverrides: [],
activateable: false,
associateEntityType: 'Feed',
associateParentEntity: 'Dashboard',
childRelationships: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object]
],
compactLayoutable: false,
createable: false,
custom: false,
customSetting: false,
deepCloneable: false,
defaultImplementation: null,
deletable: true,
deprecatedAndHidden: false,
extendedBy: null,
extendsInterfaces: null,
feedEnabled: false,
fields: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object]
],
hasSubtypes: false,
implementedBy: null,
implementsInterfaces: null,
isInterface: false,
isSubtype: false,
keyPrefix: null,
label: 'Dashboard Feed',
labelPlural: 'Dashboard Feed',
layoutable: false,
listviewable: null,
lookupLayoutable: null,
mergeable: false,
mruEnabled: false,
name: 'DashboardFeed',
namedLayoutInfos: [],
networkScopeFieldName: null,
queryable: true,
recordTypeInfos: [],
replicateable: true,
retrieveable: true,
searchLayoutable: false,
searchable: false,
sobjectDescribeOption: 'FULL',
supportedScopes: [ [Object] ],
triggerable: false,
undeletable: false,
updateable: false,
urls: {
rowTemplate: '/services/data/v50.0/sobjects/DashboardFeed/{ID}',
describe: '/services/data/v50.0/sobjects/DashboardFeed/describe',
sobject: '/services/data/v50.0/sobjects/DashboardFeed'
}
},
Visual structure of one object
I think the problem could be that there are circular dependencies.
Your data model can appear to be a tree, while it is actually more like a graph. If you apply recursive search algorithms to traverse through a graph, you can get stuck in an endless loop. Due to the circular references, it would be like searching in a tree of endless depth.
The solution, is to never process an element twice. To accomplish this, you need to keep track of a collection of processed elements, and check whether they were already processed before.
Your findChildObjects function could use a Set to mark/verify that objects have been processed.
public findChildObjects(selectedObject,..., alreadyProcessed: Set) {
// make sure objects are processed only once
if (alreadyProcessed.has(selectedObject)) return [];
alreadyProcessed.add(selectedObject);
...
}
Of course, you would need to create the set in advance before calling it the first time.
const alreadyProcessed = new Set();
...
this.findChildObjects(..., ..., alreadyProcessed);
Basically, whenever you call the this.findChildObjects(...) you pass along the collection, which makes it possible to detect and skip objects that already have been processed.

Node JS [Object Map] while writing object to file

I read many posts on stackoverflow and other tutorial sites for writing object/JSON to a file, but none of the solutions worked for me.
1) Code:
let messages = await fetchMessages()
console.log(messages) // Prints an object
fs.writeFileSync('./msgdata.json', messages , 'utf-8');
2) Also tried,
fs.writeFileSync('./msgdata.json', JSON.stringify(messages) , 'utf-8');
3) Also tried,
fs.writeFile(), but get same output as above.
msgdata.json: (For 1)
[object Map]
msgdata.json: (For 2 & 3)
{}
Can someone please point out what could be causing this?
## Output of console.log(messages) ##
OUTPUT contains 10 more such objects having different id's:
channel:
TextChannel {
type: 'text',
id: '424825532274253312',
name: 'request',
position: 69,
parentID: '397363224286473987',
permissionOverwrites: [Object],
topic: null,
nsfw: false,
lastMessageID: '427143105410760704',
guild: [Object],
messages: [Object],
_typing: Map {} },
id: '427142596817846272',
type: 'DEFAULT',
content: '**Select your emoji:** __***Group 9:***__',
author:
ClientUser {
id: '407083773537350272',
username: 'Bot',
discriminator: '9256',
avatar: '9c374e719ba2ab4e69fd577005b635bf',
bot: true,
lastMessageID: null,
lastMessage: null,
verified: true,
email: null,
localPresence: {},
_typing: Map {},
friends: Collection {},
blocked: Collection {},
notes: Collection {},
premium: null,
mfaEnabled: false,
mobile: null,
settings: [Object],
guildSettings: Collection {} },
member:
GuildMember {
guild: [Object],
user: [Object],
_roles: [Array],
serverDeaf: false,
serverMute: false,
selfMute: undefined,
selfDeaf: undefined,
voiceSessionID: undefined,
voiceChannelID: undefined,
speaking: false,
nickname: null,
joinedTimestamp: 1517127343434,
lastMessageID: null,
lastMessage: null },
pinned: false,
tts: false,
nonce: undefined,
system: false,
embeds: [],
attachments: Collection {},
createdTimestamp: 1521909131007,
editedTimestamp: null,
reactions:
Collection {
'taillow:417281639777959940' => [Object],
'shroomish:417281639899463680' => [Object],
'sableye:417281640197521419' => [Object],
'ralts:417281642735075329' => [Object],
'sentret:417281644001624076' => [Object],
'shuppet:417281644291162132' => [Object],
'torchic:417281647210397706' => [Object],
'snubbull:417281647692480522' => [Object],
'sunkern:417281647763783681' => [Object],
'slowpoke:417281648653107200' => [Object],
'teddiursa:417281649537974273' => [Object],
'sneasel:417281649613471747' => [Object],
'snorunt:417281649819123712' => [Object],
'surskit:417281650163056640' => [Object],
'qwilfish:417281654629859348' => [Object],
'shelgon:417281654730522624' => [Object] },
mentions:
MessageMentions {
everyone: false,
users: Collection {},
roles: Collection {},
_content: '**Select your emoji:** __***Group
9:***__',
_client: [Object],
_guild: [Object],
_members: null,
_channels: null },
webhookID: null,
hit: null,
_edits: [] },
This is because the object returned is a Map object (MDN). When you JSON.strigify a Map object, it always returns {}. There are two ways to get readable JSON that stores your map. The first is to loop over all the entries and create a JSON (taking in consideration the keys and values). That should be simple to achieve.
Another way is to create an array from the Map and then stringify it.
fs.writeFileSync('./msgdata.json', JSON.stringify([...myObject]) , 'utf-8');
You can define Map.prototype.toJSON which works, but it isn't standard and is discouraged. It is automatically called by JSON.stringify if it finds it.
Map.prototype.toJSON = function() {return [...this];};
console.log(JSON.stringify(messages));
A better way is to define your own replacer function (and reviver function too if you need to reconstruct map from JSON). Here I also wrap the map representing array in a special object to tell maps and ordinary arrays apart in JSON:
function replacer (key, value) {
if (value instanceof Map) {
return {
_type: "map",
map: [...value],
}
} else return value;
}
function reviver (key, value) {
if (value._type == "map") return new Map(value.map);
else return value;
}
let str = JSON.stringify(messages, replacer);
let msg = JSON.parse(str, reviver);
The error you are getting about circular structure means that some objects/arrays there contain references to itself. When you store messages you don't need to store all the information related to the channels etc and instead only store ids. So that means extending replacer for TextChannels, ClientUsers, GuildMembers etc:
if (value instanceof TextChannel) {
return {
_type: "TextChannel",
id: value.id,
};
}
var util = require('util');
fs.writeFileSync('./data.json', util.inspect(obj) , 'utf-8');
Ref. Write objects into file with Node.js

Node.js - Access key from object

I try to access a key from an object I get back from an API but when I do so, I get the key of the object in a strange format.
This is what I get when I console.log the object (booking):
{ createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers:
List [
{ value: 100,
code: 'vouchercode',
...
}
]
}
When I then try to console.log the "vouchers" key:
booking.vouchers
I get this:
{ [Function: f]
_receiver: {
createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers: List [ [Object] ] },
_scope:
{ where: { bookingId: 5ab8db29b24991b50704445a },
collect: 'voucher',
include: 'voucher' },
_targetClass: 'Voucher',
find: [Function],
getAsync: [Function],
...,
}
Why do I get it in this format and how do I convert it to a normal object like this?:
vouchers: [
{ value: 100,
code: 'vouchercode',
...
}
]
I hope the problem is understandable and some of you can help :)
Edit:
This is my code:
Booking.findById id, {include:[ 'vouchers']}, (err, booking)->
console.log booking
vouchers = booking.vouchers
console.log vouchers
*Note: I know this is coffeescript but I don't think thats the problem

Node JS - pull VAR out of array

I trying to scrape data off a website. What is returned to me is an array that looks like.
var $ = cheerio.load(body)
returns:
{ [Function]
fn:
{ constructor: [Circular],
_originalRoot:
{ type: 'root',
name: 'root',
attribs: {},
children: [Object],
next: null,
prev: null,
parent: null } },
load: [Function],
html: [Function],
xml: [Function],
text: [Function],
parseHTML: [Function],
root: [Function],
contains: [Function],
The child object is what I'm after so...
var obj = $.root()[0]
returns:
{ type: 'root',
name: 'root',
attribs: {},
children:
[ { data: 'var usdata_real = { // All_data node opens\n\n\tATL: { // Country tag opens\n\t\tid: "ATL",\n\t\t\tdata: { // Data node begins\n\t\t\tq1_1980: 169.304888373489,\n\t\t\tq2_1980: 164.585093140904,\n\t\t\tq3_1980: 166.167521028595,\n\t\t\tq4_1980: 163.
....
I want the 'data' in this array.
obj = obj['children'][0]['data']
returns:
var usdata_real = { // All_data node opens
ATL: { // Country tag opens
id: "ATL",
data: { // Data node begins
q1_1980: 169.304888373489,
q2_1980: 164.585093140904,
q3_1980: 166.167521028595,
q4_1980: 163.040844286677,
q1_1981: 163.31019903107,
q2_1981: 162.449966027231,
q3_1981: 158.719442789479,
q4_1981: 162.744884934737,
.....
which is ALMOST perfect. Except it returns to me an array which is no bueno. I want to be able treat this as an object so i can do something like
obj['ATL']
and get they KEY/VALUE pairs.
So my question....
Is it possible to strip out the object in this array ('var usdata_real'). Because that is what I'm after.
Any tips would be greatly appreciated.
Thanks!

Javascript: how to loop and change key name?

How can I change key name but key its values?
For instance I have this json data that I have stored:
{ particles:
{ name: 'particles',
values: [ [Object], [Object], [Object], [Object], [Object] ] },
timestamps:
{ name: 'timestamps',
values: [ [Object], [Object], [Object], [Object], [Object] ] }
}
And I will loop this input and change the key:
{ particles: 'particle', timestamps: 'timestamp' }
Change particles to particle and timestamps to timestamp
My attemp:
for (var property in data) {
stored[data[property]] = stored[property].values;
stored[property].name = data[property];
}
I only managed to change the name's value inside the stored data but not the key name...
Any ideas?
Assign new property by getting old property value and then delete old property.
var data = {
particles: {
name: 'particles',
values: []
},
timestamps: {
name: 'timestamps',
values: []
}
}
var newK = {
particles: 'particle',
timestamps: 'timestamp'
};
// get all object keys and iterate over them
Object.keys(newK).forEach(function(ele) {
// assign object property based on old property value
data[newK[ele]] = data[ele];
// update name property
data[newK[ele]].name = newK[ele];
// delete old object property
delete data[ele];
})
console.log(data);
You can achieve it by iterating the data and create the new keys and delete the old ones.
E.g.
var data = {
particles: {
name: 'particles',
values: [ [Object], [Object], [Object], [Object], [Object] ]
},
timestamps: {
name: 'timestamps',
values: [ [Object], [Object], [Object], [Object], [Object] ]
}
};
var res = { particles: 'particle', timestamps: 'timestamp' };
for (var k in res) {
var newValue = res[k];
data[newValue] = data[k];
data[newValue].name = newValue;
delete data[k];
}
You first have to remove the key using the delete statement after that you can add the new property using the Static method of the Object class using the defineProperty method. Here it is sample code.
var data={ particles: 'particle', timestamps: 'timestamp' };
for(var k in data){
document.write(k+":"+data[k]+"<br/>");
}
if(data.hasOwnProperty("particles")){
value=data["particles"];
delete data["particles"];
Object.defineProperty(data,"particle",{
value: value,
writable: true,
enumerable: true,
configurable: true,
});
}
if(data.hasOwnProperty("timestamps")){
value=data["timestamps"];
delete data["timestamps"];
Object.defineProperty(data,"timestamp",{
value: value,
writable: true,
enumerable: true,
configurable: true,
});
}
document.write("<br/>new values <br/>");
for(var k in data){
document.write(k+":"+data[k]+"<br/>");
}
Happy Coding!!!
:)
You can convert your Object to a String using JSON.stringify, then replace any occurrences of particles or timestamps (str.replace(/particles/g, "particle")). Finally, convert your string back to an Object using JSON.parse(str).
NB: to make sure that you will not alter any other data but the keys:
str.replace(/{"particles":{"name":"particles"/g, '{"particle":{"name":"particle"')

Categories

Resources