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

[
{
"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"}}
]
}
}
}
}
}

Related

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": {}
}

Unable to validate complete JSON schema using tv4

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

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 score by max relevance match in array elements in ElasticSearch?

I have an autocomplete analyser for a field("keywords"). This field is an array of strings. When I query with a search string I want to show first the documents where a single element of the array keywords matches best. The problem is that if a part of the string matches with more elements of the array "keywords", then this document appears before another that has less but better matches. For example, if I have a query with the word "gas station" the returning documents' keywords are these:
"hits": [
{
"_index": "locali_v3",
"_type": "categories",
"_id": "5810767ddc536a03b4761acd",
"_score": 3.1974547,
"_source": {
"keywords": [
"Radio Station",
"Radio Station"
]
}
},
{
"_index": "locali_v3",
"_type": "categories",
"_id": "581076d8dc536a03b4761cc3",
"_score": 3.0407648,
"_source": {
"keywords": [
"Stationery Store",
"Stationery Store"
]
}
},
{
"_index": "locali_v3",
"_type": "categories",
"_id": "5810767ddc536a03b4761ace",
"_score": 2.903595,
"_source": {
"keywords": [
"TV Station",
"TV Station"
]
}
},
{
"_index": "locali_v3",
"_type": "categories",
"_id": "581076cddc536a03b4761c87",
"_score": 2.517158,
"_source": {
"keywords": [
"Praktoreio Ugrwn Kausimwn/Gkaraz",
"Praktoreio Ygrwn Kaysimwn/Gkaraz",
"Praktoreio Ugron Kausimon/Gkaraz",
"Praktoreio Ygron Kaysimon/Gkaraz",
"Πρακτορείο Υγρών Καυσίμων/Γκαράζ",
"Gas Station"
]
}
}
The "Gas Station" is fourth, although it has the best single element matching. Is there a way to tell ElasticSearch that I do not care about how many times "gas" or "station" appears in keywords? I want the max element of the array keywords match as the score factor.
My settings are:
{
"locali": {
"settings": {
"index": {
"creation_date": "1480937810266",
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": "1",
"max_gram": "20"
}
},
"analyzer": {
"keywords": {
"filter": [
"lowercase",
"autocomplete_filter"
],
"char_filter": [
"my_char_filter"
],
"type": "custom",
"tokenizer": "standard"
}
},
"char_filter": {
"my_char_filter": {
"type": "mapping",
"mappings": [
"ί => ι",
"Ί => Ι",
"ή => η",
"Ή => Η",
"ύ => υ",
"Ύ => Υ",
"ά => α",
"Ά => Α",
"έ => ε",
"Έ => Ε",
"ό => ο",
"Ό => Ο",
"ώ => ω",
"Ώ => Ω",
"ϊ => ι",
"ϋ => υ",
"ΐ => ι",
"ΰ => υ"
]
}
}
},
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "TJjOt9L9QE2HrsUFHM6zJg",
"version": {
"created": "2040099"
}
}
}
}
}
And the mappings:
{
"locali": {
"mappings": {
"places": {
"properties": {
"formattedCategories": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"keywords": {
"type": "string",
"analyzer": "keywords"
},
"loc": {
"properties": {
"coordinates": {
"type": "geo_point"
}
}
},
"location": {
"properties": {
"formattedAddress": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"locality": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"neighbourhood": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
}
}
},
"name": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"rating": {
"properties": {
"rating": {
"type": "long"
}
}
},
"seenDetails": {
"type": "long"
},
"verified": {
"type": "long"
}
}
},
"regions": {
"properties": {
"keywords": {
"type": "string",
"analyzer": "keywords"
},
"loc": {
"properties": {
"coordinates": {
"type": "geo_point"
}
}
},
"name": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"type": {
"type": "long"
},
"weight": {
"type": "long"
}
}
},
"categories": {
"properties": {
"keywords": {
"type": "string",
"analyzer": "keywords"
},
"name": {
"properties": {
"english": {
"type": "string"
},
"greek": {
"type": "string"
}
}
},
"weight": {
"type": "long"
}
}
}
}
}
}
Can you post your query here that you are trying here as well.
I tried your example with the following query
{
"query": {"match": {
"keywords": "gas station"
}
}
}
And i got your desired result.
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.081366636,
"hits": [
{
"_index": "stack",
"_type": "type",
"_id": "AVjP6QnpdNp-z_ybGd-L",
"_score": 0.081366636,
"_source": {
"keywords": [
"Praktoreio Ugrwn Kausimwn/Gkaraz",
"Praktoreio Ygrwn Kaysimwn/Gkaraz",
"Praktoreio Ugron Kausimon/Gkaraz",
"Praktoreio Ygron Kaysimon/Gkaraz",
"Πρακτορείο Υγρών Καυσίμων/Γκαράζ",
"Gas Station"
]
}
},
{
"_index": "stack",
"_type": "type",
"_id": "AVjP5-u5dNp-z_ybGd-I",
"_score": 0.03182549,
"_source": {
"keywords": [
"Radio Station",
"Radio Station"
]
}
},
{
"_index": "stack",
"_type": "type",
"_id": "AVjP6KiKdNp-z_ybGd-K",
"_score": 0.03182549,
"_source": {
"keywords": [
"TV Station",
"TV Station"
]
}
}
]
}
}
Try this query to see if you are getting desired result. Also you can reply with your mappings, query and ES version if this does't work for you.
Hope this solves your problem. Thanks

Resources