Unable to validate complete JSON schema using tv4 - arrays

Total newb here.
I'm wondering if someone can help because i'm at a loss! I'm trying to assert that the response from a GET API Call meets this monster schema set - Using console.log() it looks like each of the properties is accessed successfully and if i change the object type the test will fail as i'd expect.
Working down the schema - If i try and change a property in the data array i.e from string to boolean the test will still pass although it doesn't meet the required schema i've defined,
Any guidance is massively appreciated!
//Test the schema is valid
const schema = {
"type": "object",
"properties": {
"current_page": {
"type": "integer"
},
"data": {
"type": "array",
"properties": {
"id": {
"type": "integer"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"telephone": {
"type": "string"
},
"postcode": {
"type": "string"
},
"date_of_birth": {
"type": "string"
},
"profession": {
"type": "string"
},
"time_served": {
"type": "integer"
},
"national_insurance_number": {
"type": "string"
},
"employer": {
"type": "string"
},
"lco_id": {
"type": "integer"
},
"company_employed": {
"type": "null"
},
"company_employed_email": {
"type": "null"
},
"company_employed_telephone": {
"type": "string"
},
"company_employed_address": {
"type": "null"
},
"apprentice": {
"type": "boolean"
},
"apprentice_trade": {
"type": "string"
},
"apprentice_course": {
"type": "string"
},
"apprentice_started_at": {
"type": "string"
},
"apprentice_ended_at": {
"type": "string"
},
"work_experience": {
"type": "boolean"
},
"work_experience_trade": {
"type": "null"
},
"work_experience_education": {
"type": "null"
},
"work_experience_started_at": {
"type": "null"
},
"work_experience_ended_at": {
"type": "null"
},
"nvq": {
"type": "boolean"
},
"nvq_trade": {
"type": "string"
},
"nvq_education": {
"type": "string"
},
"nvq_started_at": {
"type": "string"
},
"nvq_ended_at": {
"type": "string"
},
"unemployed": {
"type": "boolean"
},
"unemployed_months": {
"type": "null"
},
"company_employed_postcode": {
"type": "string"
},
"partner_relationship": {
"type": "null"
},
"self_partner_relationship": {
"type": "null"
},
"emergency_contact_first_name": {
"type": "string"
},
"emergency_contact_last_name": {
"type": "string"
},
"emergency_contact_telephone": {
"type": "string"
},
"enrollment_id": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"mode_of_travel": {
"type": "string"
},
"driver_or_passenger": {
"type": "string"
},
"fuel_type": {
"type": "string"
},
"engine_capacity": {
"type": "string"
},
"rtw_declaration": {
"type": "boolean"
},
"rtw_proof1_upload_id": {
"type": "null"
},
"rtw_proof2_upload_id": {
"type": "null"
},
"card_type": {
"type": "string"
},
"gender": {
"type": "string"
},
"self_gender": {
"type": "null"
},
"marital_status": {
"type": "string"
},
"disability_act": {
"type": "string"
},
"disability_description": {
"type": "null"
},
"ethnic_origin": {
"type": "string"
},
"religion": {
"type": "string"
},
"nationality": {
"type": "string"
},
"sexual_orient": {
"type": "string"
},
"checked_membership": {
"type": "integer"
},
"training_checked": {
"type": "integer"
},
"enrollment": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"inducted": {
"type": "boolean"
},
"user_id": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"expiry_date": {
"type": "string"
},
"user": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"email": {
"type": "string"
},
"role": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"state": {
"type": "integer"
},
"last_login_at": {
"type": "null"
}
},
"required": [
"id",
"email",
"role",
"created_at",
"updated_at",
"state",
"last_login_at"
]
}
},
"required": [
"id",
"inducted",
"user_id",
"created_at",
"updated_at",
"expiry_date",
"user"
]
}
},
"required": [
"id",
"first_name",
"last_name",
"telephone",
"postcode",
"date_of_birth",
"profession",
"time_served",
"national_insurance_number",
"employer",
"lco_id",
"company_employed",
"company_employed_email",
"company_employed_telephone",
"company_employed_address",
"apprentice",
"apprentice_trade",
"apprentice_course",
"apprentice_started_at",
"apprentice_ended_at",
"work_experience",
"work_experience_trade",
"work_experience_education",
"work_experience_started_at",
"work_experience_ended_at",
"nvq",
"nvq_trade",
"nvq_education",
"nvq_started_at",
"nvq_ended_at",
"unemployed",
"unemployed_months",
"company_employed_postcode",
"partner_relationship",
"self_partner_relationship",
"emergency_contact_first_name",
"emergency_contact_last_name",
"emergency_contact_telephone",
"enrollment_id",
"created_at",
"updated_at",
"mode_of_travel",
"driver_or_passenger",
"fuel_type",
"engine_capacity",
"rtw_declaration",
"rtw_proof1_upload_id",
"rtw_proof2_upload_id",
"card_type",
"gender",
"self_gender",
"marital_status",
"disability_act",
"disability_description",
"ethnic_origin",
"religion",
"nationality",
"sexual_orient",
"checked_membership",
"training_checked",
"enrollment",
]
},
}
}
// Use tiny validator to validate the results - Error if there are additional properties, and check recursion.
pm.test("Validate schema contains the relevant details", () => {
tv4.validateMultiple(jsonData, schema, true, true);
var jsonData = JSON.parse(responseBody);
// Log all errors to the console
var validationResult = tv4.validateMultiple(jsonData, schema, true, true);
for (var i = 0; i < validationResult.errors.length; i++) {
console.log("path :" + validationResult.errors[i].dataPath + " message :" + validationResult.errors[i].message);
}
});

const schema = {
"type": "object",
"properties": {
"current_page": {
"type": "boolean"
}
}
}
pm.test("Validate schema contains the relevant details", () => {
var jsonData = { "current_page": 2 }
// Log all errors to the console
var validationResult = tv4.validateMultiple(jsonData, schema, true, true);
validationResult.valid ? null : console.log(JSON.stringify(validationResult, null, 2))
pm.expect(validationResult.valid, JSON.stringify(validationResult, null, 2)).to.be.true
});
you don't have expect to assert it that's why it passes always , also as Danny mentioned use
const schema = {
"type": "object",
"properties": {
"current_page": {
"type": "boolean"
}
}
}
pm.test("Validate schema contains the relevant details", () => {
var jsonData = { "current_page": 2 }
pm.response.to.have.jsonSchema(schema)
});
And for array you should use items instead of property:
const schema = {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required":["id","name"]
}
}
}
}
pm.test("Validate schema contains the relevant details", () => {
var jsonData = { "data": [{ "id": 2,"name":"test" }] }
// Log all errors to the console
var validationResult = tv4.validateMultiple(jsonData, schema, true, true);
validationResult.valid ? null : console.log(JSON.stringify(validationResult, null, 2))
pm.expect(validationResult.valid, JSON.stringify(validationResult, null, 2)).to.be.true
});
you can create schema with so much ease using :
https://www.jsonschema.net/login

Related

How to validate dynamic API response (Schema validation) in Postman

Hello there I have a API that sends dynamic responses and I want to validate the schema of that response.following is the response I am trying to validate.
{
"Data": [
{
"CustomerName": "BeautyProductions",
"Websites": {
"storeone": {
"Keyone":"testvalueone",
"Keytwo":"testvalue two"
}
}
}
]
}
But the thing is the number of websites increases sometimes like following
{
"Data": [
{
"CustomerName": "BeautyProductions",
"Websites": {
"storeone": {
"Keyone":"testvalueone",
"Keytwo":"testvalue two"
},
"storetwo": {
"Keyone":"testvaluestoretwo",
"Keytwo":"testvaluestoretwonow"
}
}
}
]
}
I tried to validate schema as following
var schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"Data": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"CustomerName": {
"type": "string"
},
"Websites": {
"type": "object",
"properties": {
"storeone": {
"type": "object",
"properties": {
"Keyone": {
"type": "string"
},
"Keytwo": {
"type": "string"
}
},
"required": [
"Keyone",
"Keytwo"
]
}
},
"required": [
"storeone"
]
}
},
"required": [
"CustomerName",
"Websites"
]
}
]
}
},
"required": [
"Data"
]
}
var json = pm.response.json()
pm.test('shcema is valid', function(){
pm.expect(tv4.validate(json, schema)).to.be.true;
})
But it fails when the number of website count is increasing. SO, I would liketo know how I can validate this?
Thankyou
I don't know if the "stored" field is required, but you can use the "additionalProperties". The "additionalProperties" field allows you to specify a schema for properties in the object that are not explicitly defined in the properties field.
Please try below schema if it works:
var schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"Data": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"CustomerName": {
"type": "string"
},
"Websites": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"Keyone": {
"type": "string"
},
"Keytwo": {
"type": "string"
}
},
"required": [
"Keyone",
"Keytwo"
]
}
}
},
"required": [
"CustomerName",
"Websites"
]
}
]
}
},
"required": [
"Data"
]
}

LogicApp - How to check if collection is empty

What I would like to do it if there is addOn array, I would like to append the word "xxx" to the end of the name.
Schema applied to message.
{
"properties": {
"appointment": {
"properties": {
"id": {
"type": "integer"
},
"lines": {
"items": {
"properties": {
"addOn": {
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"type": "array"
},
"id": {
"type": "integer"
},
"price": {
"type": "integer"
}
},
"required": [
"id",
"price"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"messageId": {
"type": "string"
}
},
"type": "object"
}
Message 1
{
"messageId": "11",
"appointment": {
"id": 22,
"lines": [
{
"id": 33,
"price": 125.0,
"addOn": [
{
"id": 44,
"name": "test"
}
]
}
]
}
}
Message 2
{
"messageId": "11",
"appointment": {
"id": 22,
"lines": [
{
"id": 33,
"price": 125.0
}
]
}
}
Message 1 works fine but whenever I try and use length or Parse Array I get a message that addOn is null.
How can I put a proper Condition express to not get any errors or do nothing when there is no addOn array.
Logic App.
Message1 - Okay
Message2 - Error
Code View.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_each": {
"actions": {
"For_each_2": {
"actions": {
"Condition_3": {
"actions": {},
"expression": {
"and": [
{
"equals": [
"#empty(items('For_each_2'))",
"True"
]
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "#items('For_each')['addOn']",
"runAfter": {},
"type": "Foreach"
}
},
"foreach": "#body('Parse_JSON')?['appointment']?['lines']",
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Foreach"
},
"Parse_JSON": {
"inputs": {
"content": "#triggerBody()",
"schema": {
"properties": {
"appointment": {
"properties": {
"id": {
"type": "integer"
},
"lines": {
"items": {
"properties": {
"addOn": {
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"type": "array"
},
"id": {
"type": "integer"
},
"price": {
"type": "integer"
}
},
"required": [
"id",
"price"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"messageId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {
"properties": {
"appointment": {
"properties": {
"id": {
"type": "integer"
},
"lines": {
"items": {
"properties": {
"addOn": {
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"type": "array"
},
"id": {
"type": "integer"
},
"price": {
"type": "integer"
}
},
"required": [
"id",
"price",
"addOn"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"messageId": {
"type": "string"
}
},
"type": "object"
}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
Steve
I would like to append the word "xxx" to the end of the name.
For appending you can directly add while setting the "name" variable.
Alternatively, you can also use concat function as below.
concat(body('Parse_JSON')?['appointment']?['lines'][0]['addOn'][0]['name'],variables('xxx'))
where both cases would give the result as the following
How can I put a proper Condition express to not get any errors or do nothing when there is no addOn array.
You can do this in many ways where one of the workarounds would be using if the lines contain "addOn" or not.
"contains": ["#body('Parse_JSON')?['appointment']?['lines'][0]","addOn"]
MESSAGE1 RESULTS:
MESSAGE2 RESULTS:
You can reproduce the same in your logic app using the below codeview
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": "#variables('Message')",
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "Compose"
},
"For_each": {
"actions": {
"Condition": {
"actions": {
"Set_variable": {
"inputs": {
"name": "Message",
"value": {
"appointment": {
"id": "#body('Parse_JSON')?['appointment']?['id']",
"lines": [
{
"addOn": "addOn is NULL",
"id": "#items('For_each')?['id']",
"price": "#items('For_each')?['price']"
}
]
},
"messageId": "#{body('Parse_JSON')?['messageId']}"
}
},
"runAfter": {},
"type": "SetVariable"
}
},
"else": {
"actions": {
"For_each_2": {
"actions": {
"Set_variable_2": {
"inputs": {
"name": "Message",
"value": {
"appointment": {
"id": "#body('Parse_JSON')?['appointment']?['id']",
"lines": [
{
"addOn": [
{
"id": "#items('For_each_2')?['id']",
"name": "#{concat(body('Parse_JSON')?['appointment']?['lines'][0]['addOn'][0]['name'],variables('xxx'))}"
}
],
"id": "#items('For_each')?['id']",
"price": "#items('For_each')?['price']"
}
]
},
"messageId": "#{body('Parse_JSON')?['messageId']}"
}
},
"runAfter": {},
"type": "SetVariable"
}
},
"foreach": "#items('For_each')['addOn']",
"runAfter": {},
"type": "Foreach"
}
}
},
"expression": {
"and": [
{
"not": {
"contains": [
"#body('Parse_JSON')?['appointment']?['lines'][0]",
"addOn"
]
}
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "#body('Parse_JSON')?['appointment']?['lines']",
"runAfter": {
"Initialize_variable_xxx": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "Message",
"type": "object"
}
]
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_variable_xxx": {
"inputs": {
"variables": [
{
"name": "xxx",
"type": "string",
"value": "xxx"
}
]
},
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Parse_JSON": {
"inputs": {
"content": "#triggerBody()",
"schema": {
"properties": {
"appointment": {
"properties": {
"id": {
"type": "integer"
},
"lines": {
"items": {
"properties": {
"addOn": {
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"type": "array"
},
"id": {
"type": "integer"
},
"price": {
"type": "integer"
}
},
"required": [
"id",
"price"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"messageId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {
"properties": {
"appointment": {
"properties": {
"id": {
"type": "integer"
},
"lines": {
"items": {
"properties": {
"addOn": {
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"type": "array"
},
"id": {
"type": "integer"
},
"price": {
"type": "integer"
}
},
"required": [
"id",
"price",
"addOn"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"messageId": {
"type": "string"
}
},
"type": "object"
}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}

Azure Logic App HTTP Post JSON to SQL Row

I'm building a Logic app that takes Wordpress Woocommerce Data as HTTP-POST JSON and puts it into a MSSQL Database.
Setup-
HTTP Post URL
SQL Connection
Response 200
When I build the SQL Connection under the design view it creates a for each expression on Products and Coupon.
I get
ExpressionEvaluationFailed. The execution of template action 'For_each' failed: the result of the evaluation of 'foreach' expression '#triggerBody()' is of type 'Null'. The result must be a valid array.
when trying to run the code.
The table is setup with the columns correctly and they map on the design view but i'm not sure why I'm getting the ExpressionEvaluationFailed.
Note:Removed subscription id for security.
Any help would be greatly appreciated. I know that it has something to do with the arrays.
JSON SCHEMA for HTTP POST
{
"items": {
"properties": {
"Customer User Email": {
"type": "string"
},
"Customer User ID": {
"type": "string"
},
"billing_address": {
"type": "string"
},
"billing_city": {
"type": "string"
},
"billing_company": {
"type": "string"
},
"billing_country": {
"type": "string"
},
"billing_email": {
"type": "string"
},
"billing_first_name": {
"type": "string"
},
"billing_last_name": {
"type": "string"
},
"billing_phone": {
"type": "string"
},
"billing_postcode": {
"type": "string"
},
"billing_state": {
"type": "string"
},
"cart_discount": {
"type": "string"
},
"coupons": {
"items": {
"properties": {
"code": {
"type": "string"
},
"discount_amount": {
"type": "string"
},
"discount_amount_tax": {
"type": "string"
}
},
"required": [
"code",
"discount_amount",
"discount_amount_tax"
],
"type": "object"
},
"type": "array"
},
"customer_note": {
"type": "string"
},
"order_date": {
"type": "string"
},
"order_number": {
"type": "string"
},
"order_refund": {
"type": "integer"
},
"order_shipping": {
"type": "string"
},
"order_status": {
"type": "string"
},
"order_subtotal": {
"type": "string"
},
"order_total": {
"type": "string"
},
"order_total_tax": {
"type": "integer"
},
"payment_method_title": {
"type": "string"
},
"products": {
"items": {
"properties": {
"item_price": {
"type": "integer"
},
"line_id": {
"type": "integer"
},
"name": {
"type": "string"
},
"qty": {
"type": "string"
},
"sku": {
"type": "string"
}
},
"required": [
"line_id",
"sku",
"name",
"qty",
"item_price"
],
"type": "object"
},
"type": "array"
},
"shipping_address": {
"type": "string"
},
"shipping_city": {
"type": "string"
},
"shipping_country": {
"type": "string"
},
"shipping_first_name": {
"type": "string"
},
"shipping_last_name": {
"type": "string"
},
"shipping_method_title": {
"type": "string"
},
"shipping_postcode": {
"type": "string"
},
"shipping_state": {
"type": "string"
}
},
"required": [
"order_number",
"order_status",
"order_date",
"customer_note",
"Customer User ID",
"Customer User Email",
"billing_first_name",
"billing_last_name",
"billing_company",
"billing_address",
"billing_city",
"billing_state",
"billing_postcode",
"billing_country",
"billing_email",
"billing_phone",
"shipping_first_name",
"shipping_last_name",
"shipping_address",
"shipping_city",
"shipping_state",
"shipping_postcode",
"shipping_country",
"shipping_method_title",
"payment_method_title",
"cart_discount",
"order_subtotal",
"order_shipping",
"order_refund",
"order_total",
"order_total_tax",
"products",
"coupons"
],
"type": "object"
},
"type": "array"
}
Logic App Code View
{
"$connections": {
"value": {
"sql_1": {
"connectionId": "/subscriptions/---/resourceGroups/cogpubwebapps/providers/Microsoft.Web/connections/sql-3",
"connectionName": "sql-3",
"id": "/subscriptions/---/providers/Microsoft.Web/locations/eastus/managedApis/sql"
}
}
},
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_each": {
"actions": {
"For_each_2": {
"actions": {
"For_each_3": {
"actions": {
"Insert_row": {
"inputs": {
"body": {
"Customer_User_Email": "#items('For_each')['Customer User Email']",
"Customer_User_ID": "#items('For_each')['Customer User ID']",
"billing_address": "#items('For_each')['billing_address']",
"billing_city": "#items('For_each')['billing_city']",
"billing_company": "#items('For_each')['billing_company']",
"billing_country": "#items('For_each')['billing_country']",
"billing_email": "#items('For_each')['billing_email']",
"billing_first_name": "#items('For_each')['billing_first_name']",
"billing_last_name": "#items('For_each')['billing_last_name']",
"billing_phone": "#items('For_each')['billing_phone']",
"billing_postcode": "#items('For_each')['billing_postcode']",
"billing_state": "#items('For_each')['billing_state']",
"cart_discount": "#items('For_each')['cart_discount']",
"coupons0code": "#items('For_each_3')['code']",
"coupons0discount_amount": "#items('For_each')['cart_discount']",
"coupons0discount_amount_tax": "#items('For_each_3')['discount_amount_tax']",
"customer_note": "#items('For_each')['customer_note']",
"order_date": "#items('For_each')['order_date']",
"order_number": "#items('For_each') ['order_number']",
"order_refund": "#items('For_each') ['order_refund']",
"order_shipping": "#items('For_each') ['order_shipping']",
"order_status": "#items('For_each')['order_status']",
"order_subtotal": "#items('For_each') ['order_subtotal']",
"order_total": "#items('For_each') ['order_total']",
"order_total_tax": "#items('For_each')['order_total_tax']",
"payment_method_title": "#items('For_each')['payment_method_title']",
"products0item_price": "#{items('For_each_2')['item_price']}",
"products0line_id": "#{items('For_each_2')['line_id']}",
"products0name": "#items('For_each_2')['name']",
"products0qty": "#items('For_each') ['qty']",
"products0sku": "#items('For_each_2')['sku']",
"shipping_address": "#items('For_each')['shipping_address']",
"shipping_city": "#items('For_each')['shipping_city']",
"shipping_country": "#items('For_each')['shipping_country']",
"shipping_first_name": "#items('For_each')['shipping_first_name']",
"shipping_last_name": "#items('For_each')['shipping_last_name']",
"shipping_method_title": "#items('For_each')['shipping_method_title']",
"shipping_postcode": "#items('For_each')['shipping_postcode']",
"shipping_state": "#items('For_each')['shipping_state']"
},
"host": {
"connection": {
"name": "#parameters('$connections')['sql_1']['connectionId']"
}
},
"method": "post",
"path": "/datasets/default/tables/#{encodeURIComponent(encodeURIComponent('[dbo].[PWBSWebOrders]'))}/items"
},
"runAfter": {},
"type": "ApiConnection"
}
},
"foreach": "#items('For_each')['coupons']",
"runAfter": {},
"type": "Foreach"
}
},
"foreach": "#items('For_each')['products']",
"runAfter": {},
"type": "Foreach"
}
},
"foreach": "#triggerBody()",
"runAfter": {},
"type": "Foreach"
},
"Response": {
"inputs": {
"statusCode": 200
},
"kind": "Http",
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "Response"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"manual": {
"inputs": {
"method": "POST",
"schema": {
"items": {
"properties": {
"Customer User Email": {
"type": "string"
},
"Customer User ID": {
"type": "string"
},
"billing_address": {
"type": "string"
},
"billing_city": {
"type": "string"
},
"billing_company": {
"type": "string"
},
"billing_country": {
"type": "string"
},
"billing_email": {
"type": "string"
},
"billing_first_name": {
"type": "string"
},
"billing_last_name": {
"type": "string"
},
"billing_phone": {
"type": "string"
},
"billing_postcode": {
"type": "string"
},
"billing_state": {
"type": "string"
},
"cart_discount": {
"type": "string"
},
"coupons": {
"items": {
"properties": {
"code": {
"type": "string"
},
"discount_amount": {
"type": "string"
},
"discount_amount_tax": {
"type": "string"
}
},
"required": [
"code",
"discount_amount",
"discount_amount_tax"
],
"type": "object"
},
"type": "array"
},
"customer_note": {
"type": "string"
},
"order_date": {
"type": "string"
},
"order_number": {
"type": "string"
},
"order_refund": {
"type": "integer"
},
"order_shipping": {
"type": "string"
},
"order_status": {
"type": "string"
},
"order_subtotal": {
"type": "string"
},
"order_total": {
"type": "string"
},
"order_total_tax": {
"type": "integer"
},
"payment_method_title": {
"type": "string"
},
"products": {
"items": {
"properties": {
"item_price": {
"type": "integer"
},
"line_id": {
"type": "integer"
},
"name": {
"type": "string"
},
"qty": {
"type": "string"
},
"sku": {
"type": "string"
}
},
"required": [
"line_id",
"sku",
"name",
"qty",
"item_price"
],
"type": "object"
},
"type": "array"
},
"shipping_address": {
"type": "string"
},
"shipping_city": {
"type": "string"
},
"shipping_country": {
"type": "string"
},
"shipping_first_name": {
"type": "string"
},
"shipping_last_name": {
"type": "string"
},
"shipping_method_title": {
"type": "string"
},
"shipping_postcode": {
"type": "string"
},
"shipping_state": {
"type": "string"
}
},
"required": [
"order_number",
"order_status",
"order_date",
"customer_note",
"Customer User ID",
"Customer User Email",
"billing_first_name",
"billing_last_name",
"billing_company",
"billing_address",
"billing_city",
"billing_state",
"billing_postcode",
"billing_country",
"billing_email",
"billing_phone",
"shipping_first_name",
"shipping_last_name",
"shipping_address",
"shipping_city",
"shipping_state",
"shipping_postcode",
"shipping_country",
"shipping_method_title",
"payment_method_title",
"cart_discount",
"order_subtotal",
"order_shipping",
"order_refund",
"order_total",
"order_total_tax",
"products",
"coupons"
],
"type": "object"
},
"type": "array"
}
},
"kind": "Http",
"type": "Request"
}
}
}
}
Data is received from Woocommerce and put into SQL database row.

Elastic - JSON Array nested in Array

I have to index a json to Elastic which look like the below format. My problem is that the key "variable" is array that contains json objects (I thought about "nested" datatype of Elastic) but some of those objects it's possible to contain nested json arrays inside them. (see variable CUSTOMERS).
POST /example_data/data {
"process_name": "TEST_PROCESS",
"process_version ": 0,
"process_id": "1111",
"activity_id": "111",
"name": "update_data",
"username": "testUser",
"datetime": "2018-01-01 10:00:00",
"variables": [{
"name": "ΒΑΝΚ",
"data_type": "STRING",
"value": "EUROBANK"
},{
"name": "CITY",
"data_type": "STRING",
"value": "LONDON"
}, {
"name": "CUSTOMERS",
"data_type": "ENTITY",
"value": [{
"variables": [{
"name": "CUSTOMER_NAME",
"data_type": "STRING",
"value": "JOHN"
}, {
"name": " CUSTOMER_CITY",
"data_type": "STRING",
"value": "LONDON"
}
]
}
]
}, {
"name": "CUSTOMERS",
"data_type": "ENTITY",
"value": [{
"variables": [{
"name": "CUSTOMER_NAME",
"data_type": "STRING",
"value": "ΑΘΗΝΑ"
}, {
"name": " CUSTOMER_CITY ",
"data_type": "STRING",
"value": "LIVERPOOL"
}, {
"name": " CUSTOMER_NUMBER",
"data_type": "STRING",
"value": "1234567890"
}
]
}
]
}
] }
When I'm trying to index it I get the following error
{ "error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Can't merge a non object mapping [variables.value] with an object mapping [variables.value]"
}
],
"type": "illegal_argument_exception",
"reason": "Can't merge a non object mapping [variables.value] with an object mapping [variables.value]" }, "status": 400 }
Mapping
{ "example_data": {
"mappings": {
"data": {
"properties": {
"activity_id": {
"type": "text"
},
"name": {
"type": "text"
},
"process_name": {
"type": "text"
},
"process_version": {
"type": "integer"
}
"process_id": {
"type": "text"
},
"datetime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"username": {
"type": "text",
"analyzer": "greek"
},
"variables": {
"type": "nested",
"properties": {
"data_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"value": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}}}
When I remove the variable CUSTOMERS that contains the array, then It works properly because there are only json objects.
Is there a way to handle that? Thanks in advance

How to construct a JSON based query on nested object having array items with ES search?

[
{
"name": "Document 1",
"tags": {
"typeATags": ["a1"],
"typeBTags": ["b1"],
"typeCTags": ["c1"],
"typeDTags": ["d1"]
}
},
{
"name": "Document 2",
"tags": {
"typeATags": ["a2"],
"typeBTags": ["b1", "b2"],
"typeCTags": ["c2"],
"typeDTags": ["d1", "d2"]
}
},
{
"name": "Document 3",
"tags": {
"typeATags": ["a1", "a2", "a3"],
"typeBTags": ["b1", "b2", "b3"],
"typeCTags": ["c3"],
"typeDTags": ["d1", "d2", "d3"]
}
}
]
How to build a query on ES 6.0,
That will return all the records that has 'a1' and 'b1' tags ? // should return 1,3
That will return all the records that has 'a1' and 'a2' tags combined? // should return 3
That will return all the records that has 'a1' or 'a2' tags ? //should return 1,2,3
That will return all the records that has 'a1' AND ( 'c1' OR 'c3') tags ? //should return 1,2
Thanks #mickl for the Answer
Edit 1:
Here is my actual Schema,
{
"cmslocal": {
"mappings": {
"video": {
"properties": {
"assetProps": {
"properties": {
"assetType": {
"type": "string"
},
"configPath": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
},
"analyzer": "standard"
},
"contentSha1": {
"type": "string"
},
"originalPath": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
},
"analyzer": "standard"
},
"path": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
},
"analyzer": "standard"
},
"thumbnailPath": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
},
"analyzer": "standard"
}
}
},
"channel": {
"type": "string"
},
"configProps": {
"properties": {
"events": {
"type": "nested",
"include_in_root": true,
"properties": {
"Desc": {
"type": "string"
},
"Tags": {
"type": "string"
},
"UUID": {
"type": "string"
}
}
},
"roiUUID": {
"type": "string"
}
}
},
"contentSha1": {
"type": "string"
},
"eventDesc": {
"type": "string"
},
"ext": {
"type": "string"
},
"format": {
"type": "string"
},
"fovProps": {
"properties": {
"description": {
"type": "string"
},
"width": {
"type": "float"
}
}
},
"locationProps": {
"type": "nested",
"properties": {
"address": {
"type": "string"
},
"city": {
"type": "string"
},
"country": {
"type": "string"
},
"county": {
"type": "string"
},
"location": {
"type": "geo_point"
},
"postcode": {
"type": "string"
},
"state": {
"type": "string"
}
}
},
"nodeid": {
"type": "string"
},
"poleHeight": {
"type": "float"
},
"query": {
"properties": {
"bool": {
"properties": {
"filter": {
"properties": {
"term": {
"properties": {
"nodeid": {
"type": "string"
}
}
}
}
}
}
}
}
},
"retentionPolicy": {
"type": "string"
},
"siteScopeID": {
"type": "string"
},
"tagProps": {
"type": "nested",
"properties": {
"conditions": {
"type": "string"
},
"environment": {
"type": "string"
},
"events": {
"type": "string"
},
"lighting": {
"type": "string"
},
"objects": {
"type": "string"
},
"other": {
"type": "string"
},
"scenes": {
"type": "string"
},
"useCases": {
"type": "string"
},
"weather": {
"type": "string"
}
}
},
"test": {
"type": "string"
},
"title": {
"type": "string"
},
"uploadTime": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"videoProps": {
"properties": {
"bitrate": {
"type": "float"
},
"datetime": {
"type": "date",
"format": "date_hour_minute_second_millis"
},
"daySegments": {
"type": "string"
},
"duration": {
"type": "long"
},
"framerate": {
"type": "float"
},
"height": {
"type": "integer"
},
"overlaysOn": {
"type": "boolean"
},
"width": {
"type": "integer"
}
}
}
}
}
}
}
}
Please help to build the query so I can search for
Only nodeId, Only Channel, Date Range
Any of the Tags
I'm able to search for nodeId, Channel Id using
{
"query": {
"bool": {
"filter": [
{ "match": { "nodeid": "N02cff15a" } },
{ "match": { "channel": "1" } }
]
}
}
}
and I can able to Search for tagProps using
{
"nested": {
"path": "tagProps",
"query": {
"bool": {
"must": [
{ "match": { "tagProps.objects": "car" } },
{ "match": { "tagProps.objects": "truck" } }
]
}
}
}
}
Help me combine two queries so I can search for NodeId with Combination of Tags.
Since tags is a nested field you should define nested mapping before indexing your documents.
{
"mappings": {
"your_type": {
"properties": {
"tags": {
"type": "nested"
}
}
}
}
}
Now you can index your data and then you can utilize nested query syntax, for your first use case it's like:
{
"query": {
"nested": {
"path": "tags",
"query": {
"bool": {
"must": [
{ "match": { "tags.typeATags": "a1" }},
{ "match": { "tags.typeBTags": "b1" }}
]
}
}
}
}
}
Next queries can be composed of must and should, like for the last one:
{
"query": {
"nested": {
"path": "tags",
"query": {
"bool": {
"must": [
{ "match": { "tags.typeATags": "a1" }}
],
"should": [
{"match": {"tags.typeCTags": "c1"}},
{"match": {"tags.typeCTags": "c3"}}
]
}
}
}
}
}

Resources