Elasticsearch JS - Variable [x] is not defined - javascript

In a test Elasticsearch index, I have indexed a document, and I now want to update the document by setting its length property to 100. I want to do this through scripting (as this is a simplified example to illustrate my problem) via the elasticsearch package.
client.update({
index: 'test',
type: 'object',
id: '1',
body: {
script: 'ctx._source.length = length',
params: { length: 100 }
}
})
However, I receive the following error:
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[6pAE96Q][127.0.0.1:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "compile error",
"script_stack": [
"ctx._source.length = length",
" ^---- HERE"
],
"script": "ctx._source.length = length",
"lang": "painless",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Variable [length]is not defined."
}
}
},
"status": 400
}
This happens even though I have included the length property in body.params.length.
Using the following:
Elasticsearch server v6.1.1
Elasticsearch JavaScript client v14.1.0
How can I resolve this issue?

The documentation is wrong at https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-update
In their example, they put:
client.update({
index: 'myindex',
type: 'mytype',
id: '1',
body: {
script: 'ctx._source.tags += tag',
params: { tag: 'some new tag' }
}
}, function (error, response) {
// ...
});
Whilst in fact, body.script should read:
client.update({
index: 'myindex',
type: 'mytype',
id: '1',
body: {
script: {
lang: 'painless',
source: 'ctx._source.tags += params.tag',
params: { tag: 'some new tag' }
}
}
}, function (error, response) {
// ...
});
Therefore, if you change your script to:
script: {
lang: 'painless',
source: 'ctx._source.length = params.length',
params: { length: 100 }
}
it should work!
You may want to reference the Painless Examples - Updating Fields with Painless page!

Related

Sails avoid action exit on exception in loop

An Action is calling the helper function inside the loop. If the helper function raise some error then it exits with a specific code queryFailed like follows:
helpers/a/execute.js
module.exports = {
friendlyName: '',
description: '',
inputs: {},
exits: {
queryError: {
description: 'Query error'
},
success: {
description: 'yayyy!! success!'
}
},
fn: async function ({ conditions }, exits) {
let records = [],
MYSQL_QUERY = `SELECT * FROM model WHERE COLUMN = $1`;
try {
records = await Model.getDatastore().sendNativeQuery(MYSQL_QUERY, [['true']]);
}
catch (error) {
return exits.queryFailed(error);
}
return exits.success(records);
}
};
I have an action as follows that calls the above mentioned helper function.
controllers/action.js:
module.exports = {
friendlyName: 'Action',
description: 'Performs some action',
inputs: {
param1: {
description: 'param 1',
type: 'string'
},
param2: {
description: 'param 2',
type: 'ref'
}
},
exits: {
invalid: {
description: 'Invalid request',
responseType: 'invalid',
statusCode: 400
},
unexpected: {
description: 'Unexpected error',
responseType: 'unexpected',
statusCode: 500
},
success: {
description: 'success',
statusCode: 200,
outputType: 'ref'
}
},
fn: async function (inputs, exits) {
// Helper Ids
const arr = ['a', 'b'];
let response = [];
for (const element of arr) {
try {
records = await sails.helpers[element].execute.with({
conditions: conditions
});
}
catch (err) {
if (err.code === 'queryError') {
LOGGER.error('Database Error', err);
return exits.unexpected();
}
return exits.unexpected();
}
response.push(records);
}
return exits.success(response);
}
};
The issue with this is in case of an invalid query the helper function exits with queryError code as follows:
return exits.queryFailed(error);
Assuming helper a is executed successfully, if there is an error in helper b then ideally the action should not exit itself. It should continue executing and show the error in the final response for that block.
Expected Response:
{
"rows": [
{
"value": {
"id": "a",
"data": {},
"meta": {},
}
},
{
"error": {
"name": "serverError",
"statusCode": 500,
"message": "Internal server error.",
"id": 2
}
},
Current Behaviour: It's catching the queryError in the action and doing an exit with the error response:
{
"trace": "",
"error": {
"name": "serverError",
"statusCode": 500,
"message": "Internal server error"
}
}
Thank you in advance!

Authentication failed due to invalid authentication credentials or a missing Authorization header. in nodejs paypal sdk

I am trying to implement paypal subscription api in react-nodejs project.i refer https://developer.paypal.com/docs/api/subscriptions/v1/. after that i got id wit "P-*********".
What i have tried is:
in Ui Side(React) i created an event for requesting server side to create the billing plans.
in server side(nodejs) i do billingPlan create and update actions.
The code is:(nodejs)
export const paypalSubscribe = async (user, data) => {
const customerId = user.customer,
{ invoice: invoiceId } = data;
try {
const billingPlanAttributes = {
description: "Create Plan for Regular",
merchant_preferences: {
auto_bill_amount: "yes",
cancel_url: "http://www.cancel.com",
initial_fail_amount_action: "continue",
max_fail_attempts: "1",
return_url: "http://www.success.com",
setup_fee: {
currency: "USD",
value: "25"
}
},
name: "Testing1-Regular1",
payment_definitions: [
{
amount: {
currency: "USD",
value: order.price.recurringAmount
},
charge_models: [
{
amount: {
currency: "USD",
value: "10.60"
},
type: "SHIPPING"
},
{
amount: {
currency: "USD",
value: "20"
},
type: "TAX"
}
],
cycles: "0",
frequency: "MONTH",
frequency_interval: order.billingCycle,
name: "Regular 1",
type: "REGULAR"
}
],
type: "INFINITE"
};
const createdBillingPlan = await new Promise((resolve, reject) => {
Paypal.billingPlan.create(billingPlanAttributes, function (
error,
billingPlan
) {
if (error) {
reject(error);
} else {
resolve(billingPlan);
}
});
});
console.log("data123....", createdBillingPlan);
// update
var billing_plan_update_attributes = [
{
op: "replace",
path: "/",
value: {
state: "ACTIVE"
}
}
];
console.log(
"billing_plan_update_attributes",
billing_plan_update_attributes
);
const updateBillingPlan = await new Promise((resolve, reject) => {
Paypal.billingPlan.update(
createdBillingPlan.id,
billing_plan_update_attributes,
function (error, response) {
if (error) {
reject(error);
} else {
resolve(response);
}
}
);
});
const getBillingPlan = await new Promise((resolve, reject) => {
Paypal.billingPlan.get(createdBillingPlan.id, function (
error,
updatedBillingPlan
) {
if (error) {
console.log("errr", error.response);
reject(error);
} else {
console.log("updatedBillingPlan", JSON.stringify(updatedBillingPlan));
resolve(updatedBillingPlan);
updatedBillingPlan.redire
}
});
});
console.log("getBillingPlan", getBillingPlan);
return { ok: true, data: getBillingPlan };
} catch (error) {
console.log("error", error);
}
};
And i got getBillingPlan is like this:
{ id: 'P-**************',
state: 'ACTIVE',
name: 'Testing1-Regular1',
description: 'Create Plan for Regular',
type: 'INFINITE',
payment_definitions:
[ { id: 'PD-0EF41434TA3045459BCMIRMA',
name: 'Regular 1',
type: 'REGULAR',
frequency: 'Month',
amount: [Object],
cycles: '0',
charge_models: [Array],
frequency_interval: '1' } ],
merchant_preferences:
{ setup_fee: { currency: 'USD', value: '25' },
max_fail_attempts: '1',
return_url: 'http://www.success.com',
cancel_url: 'http://www.cancel.com',
auto_bill_amount: 'YES',
initial_fail_amount_action: 'CONTINUE' },
create_time: '2020-07-01T04:18:01.008Z',
update_time: '2020-07-01T04:18:02.031Z',
links:
[ { href:
'https://api.sandbox.paypal.com/v1/payments/billing-plans/P-***********',
rel: 'self',
method: 'GET' } ],
httpStatusCode: 200
}
And when i trying to open the links in links array
ie,https://api.sandbox.paypal.com/v1/payments/billing-plans/P-***********' i got the error:
"Authentication failed due to invalid authentication credentials or a missing Authorization
header."
Where i went wrong? How can i resolve this and implement subscription of paypal in my Project.
REST Api
i changed my code to rest api calls finaly i got response like this:
{ status: 'APPROVAL_PENDING',
id: 'I-1FU83BNMBCFS',
create_time: '2020-07-06T09:47:02Z',
links:
[ { href:
'https://www.sandbox.paypal.com/webapps/billing/subscriptions? ba_token=BA-3D945638N1691194P',
rel: 'approve',
method: 'GET' },
{ href:
'https://api.sandbox.paypal.com/v1/billing/subscriptions/I- 1FU83BNMBCFS',
rel: 'edit',
method: 'PATCH' },
{ href:
'https://api.sandbox.paypal.com/v1/billing/subscriptions/I-1FU83BNMBCFS',
rel: 'self',
method: 'GET' } ],
responseCode: 201 }
and in my ui side i opened the approval link in new window after submitting it shows 404. Why?
code:
window.open(URL, "_blank");
UPDATE:Subscription:
const subscriptionString = {
plan_id: result.id,
start_time: "2021-11-01T00:00:00Z",
shipping_amount: {
currency_code: "USD",
value: "10.00"
},
subscriber: {
name: {
given_name: "John",
surname: "Doe"
},
email_address: "customer#example.com",
shipping_address: {
name: {
full_name: "John Doe"
},
address: {
address_line_1: "2211 N First Street",
address_line_2: "Building 17",
admin_area_2: "San Jose",
admin_area_1: "CA",
postal_code: "95131",
country_code: "US"
}
}
},
application_context: {
brand_name: "walmart",
locale: "en-US",
shipping_preference: "SET_PROVIDED_ADDRESS",
user_action: "SUBSCRIBE_NOW",
payment_method: {
payer_selected: "PAYPAL",
payee_preferred: "IMMEDIATE_PAYMENT_REQUIRED"
},
return_url: "https://example.com/returnUrl",
cancel_url: "https://example.com/cancelUrl"
}
},
options = {
url: "https://api.sandbox.paypal.com/v1/billing/subscriptions",
method: "POST",
headers: headers,
body: JSON.stringify(subscriptionString)
},
activateResult = await payment.callPayaplApi(options);
return {
ok: true,
data: activateResult
};
}
There is no SDK for a Subscriptions API integration, you need to implement direct REST API calls.
The PayPal-Node-SDK never supported the Subscriptions API, only the previous billing APIs which are not compatible. Also, the PayPal-Node-SDK is no longer maintained.
You particular authentication error is due to something else, but due to the above issues it is not worth troubleshooting.
Start over and integrate correctly with direct REST API calls.

How to put additional settings when index in aws elasticsearch using node.js

I'm gonna put additional settings details into client.index function.
Here's what I tried.
return client
.index({
index: indexName,
type: "file",
id: bucketName + "/" + fileKey,
body: {
title: fileName,
content: contentString,
fileKey: fileKey,
bucketName: bucketName,
updated: Date.now(),
type: fileType,
},
})
How can I put analysis details into this?
This is what I'm gonna put.
{
settings: {
analysis: {
analyze: {
tokenizer: "icu-tokenizer"
}
}
}
}
Finally it should look like this:
{
"ghej": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"number_of_shards": "5",
"provided_name": "ghej",
"creation_date": "1592239308694",
"analysis": {
"analyzer": {
"content": {
"type": "custom",
"tokenizer": "icu_tokenizer"
}
}
},
"number_of_replicas": "1",
"uuid": "1yX6z-eARdyNakJwM6Z3ow",
"version": {
"created": "7010199"
}
}
}
}
}
Any help would be appreciated.
The "settings" property needs to be inside the "body" property.
In the body you need to define analyzer/tokenizer parameters and the text on which the analysis should be performed
You can refer this official documentation
returnclient.index({
index: indexName,
type: "file",
id: bucketName+"/"+fileKey,
body: {
"settings": {
"analysis": {
"analyzer": {
"my_icu_analyzer": {
"tokenizer": "icu_tokenizer"
}
}
}
}
}
})
You can refer these blogs and answer to know more
Elasticsearch Analyzer
Custom Made Analyzer
Integrate Elasticsearch with Node.js

Fastify schema validation isn't working. Do I have something configured the wrong way?

I'm trying to figure out why the schema validation is not working in Fastify. I have the following code:
const postOptions = {
schema: {
body: {
type: 'object',
properties: {
name: { type: 'string' },
parentId: { type: 'number' },
requiredKey: { foo: { type: 'string'} }
}
},
response: {
201: {
type: 'object',
properties: {
id: { type: 'number'},
name: { type: 'string'},
parentId: { type: 'number' }
}
}
}
}
}
fastify.post('/sponsor', postOptions, async (request, reply) => {
console.log(`POST /sponsor called`)
return { id: 2, name: 'Zenotis', parentId: 1 }
})
When I use postman to test it out, I can send any keys and values with the body and it goes through fine. It seems like it's not checking at all. Same thing with response. I'm using Fastify version 2.11.0
Edit: here is the json body I'm sending:
{
"name": "Test",
"parentId": 5555555,
"foo": "bar"
}
Here's what I would expect to fail:
{
"myName": "the field is not name",
"parentID": "The D is capitalized and this is a string",
"bar": "where did this field come from, it's not foo"
}
If I send this body, it goes through fine. How do I configure it to fail in all these cases?
Your schema use has a few fixes to apply:
if you don't set the status code 201, the response schema you set will not work. Use '2xx' or set the right code in the reply object
to remove the field that are not in the schema you need to add additionalProperties
if you don't set the required field in the schema, all the fields are optionals
Here a blocking example:
const fastify = require('fastify')()
const postOptions = {
schema: {
body: {
type: 'object',
additionalProperties: false, // it will remove all the field that is NOT in the JSON schema
required: [
'name',
'parentId',
'requiredKey'
],
properties: {
name: { type: 'string' },
parentId: { type: 'number' },
requiredKey: { foo: { type: 'string' } }
}
},
response: {
201: {
type: 'object',
properties: {
id: { type: 'number' },
name: { type: 'string' },
parentId: { type: 'number' }
}
}
}
}
}
fastify.post('/sponsor', postOptions, async (request, reply) => {
console.log('POST /sponsor called')
reply.code(201) // if you don't set the code 201, the response schema you set will not work
return request.body
})
fastify.inject({
method: 'POST',
url: '/sponsor',
payload: {
name: 'Test',
parentId: 5555555,
foo: 'bar'
}
}, (_, res) => {
console.log(res.json())
/* it will print
{
statusCode: 400,
error: 'Bad Request',
message: "body should have required property 'requiredKey'"
}
*/
})

Validations for associative models sailsJs

I am trying to build a REST API on sailsjs v0.11.0, I am looking for a way to validate all POST requests. Validation works for simple models.
Simple model example:
category.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true, // this works, the POST data is validated, if this field is missing, sails responds with an error json
unique: true
}
}
}
Associative one to many model example where validation doesnt work:
Chapter.js
module.exports = {
attributes: {
name: 'string',
categoryId: 'integer',
pages: {
type: 'string',
required: true // Sails saves the record to DB even if this field is missing.
},
owner: {
model: 'Upload'
}
}
};
Upload.js
module.exports = {
attributes: {
draftId: 'integer',
chapters: {
collection: 'Chapter',
via: 'owner'
}
}
};
EDIT:
I got it to work with the following updated Chapter.js model, but if the associated model fails validation, the sails server responds with a 500 status and a error json as shown below, While this is not an error, It should have sent a 400 status.
Updated Chapter.js:
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
categoryId: {
type: 'integer',
required: true
},
pages: {
type: 'string',
required: true
},
owner: {
model: 'Upload'
}
}
};
The Error with 500 status:
{
"error": "E_UNKNOWN",
"status": 500,
"summary": "Encountered an unexpected error",
"raw": [
{
"type": "insert",
"collection": "chapter",
"values": {
"name": "chapeterOne",
"pages": "2,3,4,5",
"owner": 12
},
"err": {
"error": "E_VALIDATION",
"status": 400,
"summary": "1 attribute is invalid",
"model": "Chapter",
"invalidAttributes": {
"categoryId": [
{
"rule": "integer",
"message": "`undefined` should be a integer (instead of \"null\", which is a object)"
},
{
"rule": "required",
"message": "\"required\" validation rule failed for input: null"
}
]
}
}
}
]
}
Is there a way to make the error message more sensible?

Categories