SuiteScript TypeError: Cannot read property "firstname" from undefined - netsuite

I have a problem that's not making any sense to me. I have created a custom search and I am using the results from that search to addSelectOptions to a select field I have added.
However when trying to simply access a value within a nested object I am getting the error message: TypeError: Cannot read property "firstname" from undefined.
Here is the code:
var sfPlayersSearch = search
.create({
id: 'customsearch_pm_sf_players_search',
title: 'SF Players Search',
type: search.Type.EMPLOYEE,
columns: [
'entityid',
'firstname',
'lastname',
'custentity_pm_ws_sf_player',
],
filters: ['custentity_pm_ws_sf_player', 'is', 'true'],
})
.run()
.getRange(0, 100);
log.debug({ title: 'SF Players', details: sfPlayersSearch });
var player1ProxyField = form.addField({
id: 'custpage_pm_ws_sf_player_1_proxy',
label: 'Player 1 Proxy',
type: ui.FieldType.SELECT,
});
var player2ProxyField = form.addField({
id: 'custpage_pm_ws_sf_player_2_proxy',
label: 'Player 2 Proxy',
type: ui.FieldType.SELECT,
});
for (var i = 0; i < sfPlayersSearch.length; i++) {
log.debug({title: 'Result', details: sfPlayersSearch[i].values.firstname});
player1ProxyField.addSelectOption({ value: sfPlayersSearch[i], text: sfPlayersSearch[i].id });
}
JSON Object:
[
[
{
"recordType": "employee",
"id": "8",
"values": {
"entityid": "Artur X",
"firstname": "Artur",
"lastname": "X",
"custentity_pm_ws_sf_player": true
}
},
{
"recordType": "employee",
"id": "50",
"values": {
"entityid": "Darryl X",
"firstname": "Darryl",
"lastname": "X",
"custentity_pm_ws_sf_player": true
}
},
{
"recordType": "employee",
"id": "1983",
"values": {
"entityid": "Douglas X",
"firstname": "Douglas",
"lastname": "X",
"custentity_pm_ws_sf_player": true
}
},
{
"recordType": "employee",
"id": "86477",
"values": {
"entityid": "Paul X",
"firstname": "Paul",
"lastname": "X",
"custentity_pm_ws_sf_player": true
}
}
]
]
Any help greatly appreciated. I have tried doing .values || {}.firstname and this returns no error, but also no result.

Search.run().getRange() returns an array of Result objects. These are what you are iterating through in your for block. The Result object does not include values but rather includes methods for access the values getValue()) and text (getText()) of each result.
Change
log.debug({title: 'Result', details: sfPlayersSearch[i].values.firstname});.
to
log.debug({title: 'Result', details: sfPlayersSearch[i].getValue('firstname')});

While #krypton 's answer is correct for what you are doing you may find it useful to use Netsuite's JSONified version of search objects like what you see in your log.
If you were writing this as a library file where you might want to work in a Map/Reduce you can normalize the search result like
.getRange(0, 100)
.map(function(sr){
return JSON.parse(JSON.stringify(sr));
});
Now your original code for values.firstname would work.
Fun fact. If you are using SS 2.1 you can use let', const, and arrow functions:
const players = search.create()...
.getRange(0, 100)
.map(sr=>(JSON.parse(JSON.stringify(sr)));

Related

Mongodb nodejs, find and display array in array

I'm looking for display a array in array after findOne.
Example my document:
"name": "test",
"Electro": [{
"name": "test2",
"level": "0",
"_id": {
"$oid": "62015643157b21f7abfcf0b0"
},
"build": [{
"artifactName": "Aventurier",
"MainStat": "HP",
"MainStatValue": "15%",
"SubStat1": "Crit%",
"SubStat1Value": "30%",
"SubStat2": "PV%",
"SubStat2Value": "9%"
}]
//////////////////////////
type is a variable (let type = Electro)
User.User_Characters.findOne({"name": 'test'}, {[type]:{$elemMatch:{'name': cn}}}).then(result => {
if(result){
console.log(result); console.log(result.Electro)
}
i need console.log(result.Electro.build)
UPDATE:
resolve -> result.Electro[0], thx Joe
I have other problems :
User.User_Characters.findOne({"name": username}, {[type]:{$elemMatch:{'name': cn}}}).then(result => {
if(result){
console.log(result)
And my result =
{
_id: new ObjectId("61fea8cfcfad2dc0c3f0f740"),
Pyro: [
{
name: 'Amber',
level: '0',
_id: new ObjectId("62015643157b21f7abfcf0aa"),
build: [{
"artifactName": "Aventurier",
"MainStat": "HP",
"MainStatValue": "15%",
"SubStat1": "Crit%",
"SubStat1Value": "30%",
"SubStat2": "PV%",
"SubStat2Value": "9%"
}]
}
]
}
I just need result = build array :
{
build: [{
"artifactName": "Aventurier",
"MainStat": "HP",
"MainStatValue": "15%",
"SubStat1": "Crit%",
"SubStat1Value": "30%",
"SubStat2": "PV%",
"SubStat2Value": "9%"
}]
}

Mongoose Find not filtering for object property inside array (MongoDB 4.4.1)

I've been trying to make a chat app and I use the following schema for messages:
const messageObject = {
sender: {type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
message: {type: String, require: true, min: 1, max: global.messageMaxLength},
time: Number,
seen: Boolean
}
const MessageSchema = mongoose.Schema({
_id: {type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
messages: [messageObject]
}, {versionKey: false}) ;
module.exports = mongoose.model('Messages', MessageSchema);
It takes in entries successfully. Example of entries:
"_id": "5fb3d971e6092d2da001bbad",
"messages": [
{
"_id": "5fc58bfe0e0ffb313c27fa0a",
"message": "Hello user",
"time": 1606781949959,
"seen": false
},
{
"_id": "5fc58c010e0ffb313c27fa0b",
"message": "Hello user",
"time": 1606781953442,
"seen": false
},
{
"_id": "5fc58c020e0ffb313c27fa0c",
"message": "Hello user",
"time": 1606781954137,
"seen": false
}
]
}
I want only the seen:false messages now, but when I try to code that in find, or aggregate, I get all the data, ie, the above records:
MessageModel.find({$and: [{_id: req.userData.userid}, {'messages.seen': false}]}).then(result => {
res.status(200).json({
message: "passed",
result,
});
})
It however works fine and returns [] if I give {"messages.seen": null}}, and 1 entry with seen: null will return an entire array.
Ive seen all forums there's no place where anybody has encountered this kind of error. Please help.
Thanks
Your message objects are nested inside a document and Mongo will only return either the full document or specific top level fields you have projected. Mongo will not filter out objects within a nested array (as is the case with your schema). So if any of the message objects within the array match the selector, the whole document itself passes the match and returns as a result.
Your options are to either:
Filter out the true/false messages within your code
Change your db structure so that you have a separate messages collection where each document is a single message. So in your example, the collection would look like:
{
"_id": "5fc58bfe0e0ffb313c27fa0a",
"parentId": "5fb3d971e6092d2da001bbad",
"message": "Hello user",
"time": 1606781949959,
"seen": false
},
{
"_id": "5fc58c010e0ffb313c27fa0b",
"parentId": "5fb3d971e6092d2da001bbad",
"message": "Hello user",
"time": 1606781953442,
"seen": false
},
{
"_id": "5fc58c020e0ffb313c27fa0c",
"parentId": "5fb3d971e6092d2da001bbad",
"message": "Hello user",
"time": 1606781954137,
"seen": false
}
And then you can query that collection with:
{ "parentId": "5fb3d971e6092d2da001bbad","seen": false}

Mongoose NodeJS Express - How to Push Data To a Specific Sub Document Object Array

thank you in advance for any help.
My problem is essentially to add data to a specific sub document.
I have the following models in my NodeJS server:
MODELS
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const dataSchema = new Schema({
time: Date,
value: String
});
const nodeSchema = new Schema({
name: String,
description: String,
number: Number,
status: String,
lastSeen: Date,
data: [dataSchema]
});
const siteSchema = new Schema({
code: String,
name: String,
description: String,
totalNodes: Number,
nodes: [nodeSchema]
});
const Site = mongoose.model('site',siteSchema);
module.exports = Site;
Which basically looks like this:
Example
{
"_id": "5fa169473a394829bc485069",
"code": "xfx3090",
"name": "Name of this site",
"description": "Some description",
"totalNodes": 2,
"__v": 0,
"nodes": [
{
"_id": "5fa1af361e085b516066d7e2",
"name": "device name",
"description": "device description",
"number": 1,
"status": "Offline",
"lastSeen": "2020-11-03T19:27:50.062Z",
"data": [
{
"Date": "2019-01-01T00:00:00.000Z",
"value": "12"
},
{
"Date": "2019-01-01T00:00:00.000Z",
"Value": "146"
}
]
},
{
"_id": "5fa1b10f4f24051520f85a58",
"name": "device name",
"description": "device description",
"number": 2,
"status": "Offline",
"lastSeen": "2020-11-03T19:35:43.409Z",
"data": [
{
"Date": "2019-01-01T00:00:00.000Z",
"Value": "555"
}
]
}
]
}
]
As you can see I have created two dummy nodes with some random data.
My question now is, say I want to add some data to Node 1. How will this code look?
I've tried many variations and attempted many different things without any luck. I know this would be easier by using the Object Id's, but I was hoping there is a way around this.
My Best result so far was with this code, but unfortunately it doesn't add any data.
addNodeData: async (req,res,next) => {
const {siteCode} = xfx3090; //req.params
const { nodeNumber } = 1; //req. params - just to show example
const nodeData = await Site.findOneAndUpdate({'code': siteCode, 'node.number': nodeNumber}, {$push: {'data':{'time': Date.now(), 'value':1223}}});
res.status(200).json({message:'success'});
}
Thank you in advance!
You need the positional operator $.
The query you want is something like this:
db.collection.update({
"_id": "5fa169473a394829bc485069",
"nodes._id": "5fa1af361e085b516066d7e2"
},
{
"$push": {
"nodes.$.data": {
"Date": "newDate",
"value": "newValue"
}
}
})
The first part is to find the document. I'm assuming nodes._id is not unique so I match _id too.
Then, with the pointer in the document you want to add the new data, you use $push into nodes.$.data. So, in the filed data there will be a new object.
A mongo plauground example is here

How to specify configurations to json2csv in express

According to the docs it's possible to provide configurations e.g include NULL or set default values when parsing JSON to CSV using the json2csv module, but I'm not able to get make it work.
Is this right?
const json2csvParser = new Parser({ fields,defaultValue : "NA",includeEmptyRows : true });
The default option works if the field is missing from the JSON data or if it is undefined, however it will not replace a null value, we can see this by testing below.
You could potentially pre-process your data to replace nulls with undefined values if you wish this behaviour.
BTW, you can also set defaults for each field, which is very useful by creating an array of field objects like so:
const fields = [{ label: 'car', value: 'car', default: 'carDefault' },
{ label: 'price', value: 'price', default: 'priceDefault' },
{ label: 'color', value: 'color', default: 'colorDefault' } ];
The Porsche and Mercedes colors are populated with the default value below because the field is missing or undefined, the BMW is not since the color is null.
const { Parser } = json2csv;
const fields = ['car', 'price', 'color']
const myCars = [
{
"car": "Audi",
"price": 40000,
"color": "blue"
}, {
"car": "BMW",
"price": 35000,
"color": null
}, {
"car": "Porsche",
"price": 60000
}, {
"car": "Mercedes",
"price": 60000,
"color": undefined
}
];
const json2csvParser = new Parser({ fields, defaultValue : "NA", includeEmptyRows : true });
const csv = json2csvParser.parse(myCars);
console.log("CSV output:");
console.log(csv);
<script src="https://cdn.jsdelivr.net/npm/json2csv"></script>

Count objects in array in an object in Frisby

I am starting to learn FrisbyJS and trying to create some assertions.
I get an json that looks like this
[
{
"articles": [
{
"article": "123-123002",
"updated": "2016-10-20T14:57:25",
"sourced balance": [],
"balance": "50.00"
},
{
"article": "100-123001",
"updated": "2016-10-20T14:41:36",
"sourced balance": [],
"balance": "10.00"
}
],
"DistrictID": [],
"WarehouseID": "SebastiansWarehouse",
"SourceID": "1234",
"City": "Stockholm",
"WarehouseName": "Sebastians Warehouse",
"WarehouseType": "STORE"
}
]
And I want to:
1. count the number of article objects
2. verify that the number X in articles array has a variable with value "123-123002"
How can I do this in Frisby?
My code currently is:
var frisby = require('frisby');
frisby.create('Mekonomen RIF1')
.get('https://10.254.8.67:9443/INTERSHOP/rest/WFS/Mekonomen-MekB2BSE-Site/-/availability/sources/1234/warehouses/SebastiansWarehouse/products/',{ strictSSL: false})
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectJSON('?',{
articles: [],
DistrictID: [],
WarehouseID: "SebastiansWarehouse",
SourceID: '1234',
City: "Stockholm",
WarehouseName: "Sebastians Warehouse",
WarehouseType: "STORE"
}
)
.expectJSON('?.articles',{
articles: [],
DistrictID: [],
WarehouseID: "SebastiansWarehouse",
SourceID: '1234',
City: "Stockholm",
WarehouseName: "Sebastians Warehouse",
WarehouseType: "STORE"
}
)
.expectMaxResponseTime(500)
.toss();
you can include
.afterJSON(json){
//json.articles can be asserted here
//some more assertion on the response
}
which will parse the response and send it as an argument which can be asserted using simple javascript conditions, statements, loops etc.

Resources