Can anyone tell me why the script below fails in the NetSuite Script Debugger on API Version 2.0? As far as I can tell, the search and the join should be valid based on supported search joins for the customer record type and available fields on the campaign record type.
require(['N/search'],
function(search) {
// `leadsource` is listed as a search join for `customer`.
// See https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2022_2/script/record/customer.html
//
// `title` is listed as a field for `campaign`.
// See https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2022_2/script/record/campaign.html
search.create({
type: search.Type.CUSTOMER,
title: 'Customers',
columns: [
'leadsource',
'leadsource.title',
'companyname',
'internalid'
]
}).run().each(function(customerResult) {
// ...
});
}
);
Below is the error I'm getting.
{
"type": "error.SuiteScriptError",
"name": "SSS_INVALID_SRCH_COLUMN_JOIN",
"message": "An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: title.",
"stack": [
"each(N/search/searchObject.js)",
"<anonymous>(adhoc$-1$debugger.user:18)",
"<anonymous>(adhoc$-1$debugger.user:1)"
],
"cause": {
"type": "internal error",
"code": "SSS_INVALID_SRCH_COLUMN_JOIN",
"details": "An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: title.",
"userEvent": null,
"stackTrace": [
"each(N/search/searchObject.js)",
"<anonymous>(adhoc$-1$debugger.user:18)",
"<anonymous>(adhoc$-1$debugger.user:1)"
],
"notifyOff": false
},
"id": "",
"notifyOff": false,
"userFacing": false
}
replace 'leadsource.title' to a javascript object { join: 'leadsource', name: 'title' }
search.create({
type: search.Type.CUSTOMER,
title: 'Customers',
columns: [
'leadsource',
{ join: 'leadsource', name: 'title' },
'companyname',
'internalid'
]
})
Or you can also try to reverse the string to 'title.leadsource' as according to the error it's trying to create a join on the title field, while it should be on the leadsource field.
Related
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)));
This is the code of my queryBuilder
In database I have two tables:
enquiry_table (contains statusId(#ManyToOne) which is a foreign key for enquiry_status_table)
enquiry_status_table
async findByLocation(qParams) {
return await getRepository(Enquiry).createQueryBuilder('enq')
.where({ location: qParams.location })
.select(['enq.id', 'enq.location', 'enqStatus.name'])
.leftJoin('enq.status', 'enqStatus')
.getMany()
}
With the above code I get following Results
{
"id": 5,
"location": "Karnataka",
"status": { <-- This is what I m getting currently with the above code
"name": "CANCELLED"
}
},
{
"id": 5,
"location": "Karnataka",
"status": "CANCELLED" <-- this is what I m expecting
},
you should add transient property like 'statusName' on enquiry_table entity.
I guess you already have property named 'status' for enquiry_status_table, so I recommended name 'statusName'.
#Column({ select: false, update: false, insert: false })
statusName: string;
and use addSelect on queryBuilder
async findByLocation(qParams) {
return await getRepository(Enquiry).createQueryBuilder('enq')
.where({ location: qParams.location })
.select(['enq.id', 'enq.location'])
.addSelect('enqStatus.name', 'statusName')
.leftJoin('enq.status', 'enqStatus')
.getMany()
}
and this is expected result
{
"id": 5,
"location": "Karnataka",
"statusName": "foo"
},
I got one solution:
getRepository(Enquiry).createQueryBuilder('enq')
.select(['enq.id AS id', 'enq.location AS location', 'enqStatus.name AS status'])
.leftJoin('enq.status', 'enqStatus')
.where(enquiryReq)
.getRawMany() <-- I returned raw data and put alias to each field :)
I am currently using the code below in node.js to find and return data on various nesting levels from a mongo database. I'd like to add another layer of nesting (as mentioned in #3).
Collection:
[
{
"title": "Category A",
"link": "a",
"items": [
{
"title": "Item C",
"link": "a-c",
"series": [
{
"title": "Item C X",
"link": "a-c-x"
},
{
"title": "Item C Y",
"link": "a-c-y"
},
]
},
{
"title": "Item D",
"link": "a-d"
}
]
},
{
"title": "Category B",
"link": "b"
}
]
The query:
const doc = await ... .findOne(
{
$or: [
{ link: id },
{ "items.link": id },
{ "items.series.link": id }
],
},
{
projection: {
_id: 0,
title: 1,
link: 1,
items: { $elemMatch: { link: id } },
},
}
);
Intended results:
(works) if link of the document is matched,
(works) there should only be an object with the title and link returned
e.g.
value of id variable: "a"
expected query result: { title: "Category A", link: "a"}
(works) if items.link of subdocument is matched,
(works) it should be the same as above + an additional element in the items array returned.
e.g.
value of id variable: "a-c"
expected query result: { title: "Category A", link: "a", items: [{ title: "Item C", link: "a-c" }]}
(works) if items.series.link of sub-subdocument is matched
(struggling with this) it should return the same as in 2. + an additional element inside the matched items.series
e.g.
value of id variable: "a-c-y"
expected query result: { title: "Category A", link: "a", items: [{ title: "Item C", link: "a-c", series: [{ title: "Item C Y", link: "a-c-y" }]}]}
current query result: The whole Category A document with all sub-documents
Questions:
a.) How do I modify the projection to return the expected output in #3 as well?
b.) Is the approach above sound in terms of reading speed from a denormalized structure? I figured there'd probably need to be indexes on link, items.link and items.series.link as they are all completely unique in the document, but maybe there is a way to achieve the above goal with a completely different approach?
Ended up with going half-way via mongodb and get the full item for both - when the item link is matched and the series link is matched:
projection: {
_id: 0,
title: 1,
link: 1,
items: { $elemMatch: { $or: [
{ link: id },
{"series.link": id }
]}},
}
After that javascript filters the series array to see if the series is matched:
doc?.items?.[0]?.series?.find(item => item.link === id)
if the js is truthy (returns an object) we matched a series, if there is a doc, but the js is falsy we matched an item result.
Although not a full mongodb solution and there is definitely room for improvement the above seems to achieve the end goal to be able to distinguish between category, item and series results.
I want to increment the field value by 1 in update query using sails(node)
Users.update({ code: referral }, { $inc: [{ referredCount: 1 }] }).then(function (update) {})
I have tried this.
Users.update({ code: referral }, { $inc: [{ referredCount: 1 }] }).then(function (update) {})
"err": {
"error": "E_UNKNOWN",
"status": 500,
"summary": "Encountered an unexpected error",
"raw": {
"name": "MongoError",
"message": "The dollar ($) prefixed field '$inc' in '$inc' is not valid for storage.",
"driver": true,
"index": 0,
"code": 52,
"errmsg": "The dollar ($) prefixed field '$inc' in '$inc' is not valid for storage."
}
}
This is the only correct way to do it.
Users.update({ code: referral }, { $inc: { referredCount: 1 } })
If its not incrementing, check whether referredCount exists in the document or not.
If it exists then check whether its not nested in another object.
Lastly also check whether, there is an actual document of the applied filter by query below.
Users.find({ code: referral })
I'm using Sequelize as an ORM for my project. I have this structure:
const Event = sequelize.define('event', {
// fields defined
});
const Question = sequelize.define('question', {
description: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: '',
validate: {
notEmpty: { msg: 'Description should be set.' }
},
},
// other fields defined
});
Event.hasMany(Question);
Question.belongsTo(Event);
Then I create an instance of the Event model, with associate, like that:
const body = {
questions: [
{ description: '' } // is obviously invalid
],
// some other fields
}
const newEvent = await Event.create(body, {
include: [ Question ]
});
If I have validation errors for the Event instance itself, it returns SequelizeValidationError where I can see the path attribute for each ValidationErrorItem. However, when I have the validation error on a child model, the path attribute for this validation error is unclear:
{
"message": "Description should be set.",
"type": "Validation error",
"path": "description",
"value": "",
"origin": "FUNCTION",
"instance": {
"required": true,
"id": null,
"description": "",
"event_id": 60,
"updated_at": "2018-06-11T12:25:04.666Z",
"created_at": "2018-06-11T12:25:04.666Z"
},
"validatorKey": "notEmpty",
"validatorName": "notEmpty",
"validatorArgs": [
{
"msg": "Description should be set."
}
],
"__raw": {
"validatorName": "notEmpty",
"validatorArgs": [
{
"msg": "Description should be set."
}
]
}
The problem is, it's unclear what caused this error and which child is invalid. When I've used Mongoose as an ORM, if I'd do the same, the path attribute would be equal to something like questions.0.description, and that is way more clear, that way you can see which child is invalid.
So, my question is: is there a way to set up the path attribute while validating the child models?
Apparently it's not presented yet, I've filed an issue on Sequelize repo, here it is: https://github.com/sequelize/sequelize/issues/9524