How to get value in nested field using Kibana scripted field? - elasticsearch

I'm new to Elastic Stack.
Here, I'm trying to get the value for "pressure" and then convert it to numeric value(string⇒numeric) using Kibana scripted field.
I tried scripted field, but it didn't work for me.
Any idea? I really appreciate your support in advance.
One of my data records is as below.
{
"_index": "production",
"_type": "_doc",
"_id": "4570df7a0d4ec1b0e624e868a5861a0f1a9a7f6c35fdsssafafsa734fb152f4bed",
"_version": 1,
"_score": null,
"_source": {
"factorycode": "AM-NY",
"productcode": "STR",
"lastupdatetime": "2020-05-28T04:16:17.590Z",
"#timestamp": "2020-05-28T04:14:48.000Z",
"massproduction": {
"errorcode": null,
"equipment": "P17470110",
"operatorldap": null,
"machinetime": null,
"quantity": "1",
"externalfilename": null,
"errorcomment": null,
"datas": {
"data": [
{
"value": "45.4",
"id": "001",
"name": "pressure"
},
{
"value": "0.45",
"id": "002",
"name": "current"
}
]
},
"ladderver": null,
"eid": null,
"setupid": null,
"model": "0",
"identificationtagid": null,
"workid": "GD606546sf0B002020040800198",
"reuse": {
"num": "0"
},
"registrydate": "2020-05-28T13:14:48",
"product": "GD604564550B00",
"line": "STRS001",
"judge": "1",
"cycletime": null,
"processcode": "OP335",
"registryutcdate": "2020-04-28T04:14:48",
"name": "massproduction"
}
},
"fields": {
"massproduction.registrydate": [
"2020-05-28T13:14:48.000Z"
],
"#timestamp": [
"2020-05-28T04:14:48.000Z"
],
"lastupdatetime": [
"2020-05-28T04:16:17.590Z"
],
"registrydate": [
"2020-05-28T13:14:48.000Z"
],
"massproduction.registryutcdate": [
"2020-05-28T04:14:48.000Z"
],
"registryutcdate": [
"2020-05-28T04:14:48.000Z"
]
},
"sort": [
158806546548000
]
}
This is my "painless" scripted field in Kibana.
for(item in params._source.massproduction.datas.data)
{
if(item.name=='pressure'){
return item.value;
}
}
return 0;

You can use Float.parseFloat(value) to convert string to float
if(params._source.massproduction!=null && params._source.massproduction.datas!=null &&params._source.massproduction.datas.data.size()>0)
{
def data = params._source.massproduction.datas.data;
if(data instanceof ArrayList)
{
for(item in data)
{
if(item.name=='pressure')
{
return Float.parseFloat(item.value);
}
}
}else
{
if(data.name=='pressure')
{
return Float.parseFloat(data.value);
}
}
}
return 0;

Related

How to convert Elasticsearch index field of string type to json?

I have an Opensearch index with a string field message defined as below:
{"name":"message.message","type":"string","esTypes":["text"],"count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false}
Sample data:
"_source" : {
"message" : {
"message" : "user: AB, from: home, to: /app1"
}
}
I would like to convert the message column into json so that I can access the values message.user, message.from and message.to individually.
How do I go about it?
You can use Json Processor.
POST /_ingest/pipeline/_simulate
{
"pipeline": {
"description": "convert json to object",
"processors": [
{
"json": {
"field": "foo",
"target_field": "json_target"
}
}
]
},
"docs": [
{
"_index": "index",
"_id": "id",
"_source": {
"foo": "{\"name\":\"message.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false}\r\n"
}
}
]
}
Response:
{
"docs": [
{
"doc": {
"_index": "index",
"_id": "id",
"_version": "-3",
"_source": {
"foo": """{"name":"message.message","type":"string","esTypes":["text"],"count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false}
""",
"json_target": {
"esTypes": [
"text"
],
"readFromDocValues": false,
"name": "message.message",
"count": 0,
"aggregatable": false,
"type": "string",
"scripted": false,
"searchable": true
}
},
"_ingest": {
"timestamp": "2022-11-09T19:38:01.16232Z"
}
}
}
]
}

How to get the total page number for pagination

I try to make my pageable data for weeks everything works but I would like to know the total number of pagination pages here are the data of my mongonDB.
{
"content": [
{
"mame": "iPhone X",
"eategory": "High-Tech",
"productId": "aDPXF7Xq",
"details": {
"vating": "00",
"stocks": "20",
"price": "800000",
"tags": [
{
"tagsl": "Apple",
"tags2": "aull",
"tags3": null
}
],
"brand": "Apple",
"description": "Iphone xX",
"picture": [
{
"picturel": "photol",
"picture2": null,
"picture3": null,
"picture4": null,
"picture5": null
}
],
"thumbnails": [
{
"thumbnaill": "thumbails 1",
"thumbnail2": null,
"thumbnail3": null,
"thumbnail4": null,
"thumbnail5": null
}
]
}
},
{
"mame": "iPhone X",
"eategory": "High-Tech",
"productId": "cjjVqOBk",
"details": {
"rating": "10",
"stocks": "20",
"price": "800000",
"tags": [
{
"tagsl": "Apple",
"tags2": "aull",
"tags3": null
}
],
"brand": "Apple",
"description": "Iphone xX",
"picture": [
{
"picturel": "photol",
"picture2": null,
"picture3": null,
"picture4": null,
"picture5": null
}
],
"thumbnails": [
{
"thumbnaill": "thumbails 1",
"thumbnail2": null,
"thumbnail3": null,
"thumbnail4": null,
"thumbnail5": null
}
]
}
},
{
"mame": "iPhone X",
"eategory": "High-Tech",
"productId": "LhKiRGr6",
"details": {
"vating": "10",
"stocks": "20",
"price": "800000",
"tags": [
{
"tagsl": "Apple",
"tags2": "aull",
"tags3": null
}
],
"brand": "Apple",
"description": "Iphone xX",
"picture": [
{
"picturel": "photol",
"picture2": null,
"picture3": null,
"picture4": null,
"picture5": null
}
],
"thumbnails": [
{
"thumbnaill": "thumbails 1",
"thumbnail2": null,
"thumbnail3": null,
"thumbnail4": null,
"thumbnail5": null
}
]
}
},
{
"mame": "iPhone X",
"eategory": "High-Tech",
"productId": "dgCvi8NJ",
"details": {
"vating": "10",
"stocks": "20",
"price": "800000",
"tags": [
{
"tagsl": "Apple",
"tags2": "aull",
"tags3": null
}
],
"brand": "Apple",
"description": "Iphone xX",
"picture": [
{
"picturel": "photol",
"picture2": null,
"picture3": null,
"picture4": null,
"picture5": null
}
],
"thumbnails": [
{
"thumbnaill": "thumbails 1",
"thumbnail2": null,
"thumbnail3": null,
"thumbnail4": null,
"thumbnail5": null
}
]
}
}
],
"pageable": {
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 20,
"paged": true,
"unpaged": false
},
"totalPages": 1,
"totalElements": 4,
"last": true,
"size": 20,
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"number": 0,
"numberOfElements": 4,
"first": true,
"empty": false
}
Now here is the data paging code
#GetMapping("/engine/search")
public PageImpl<Products> engineSearch(#RequestParam("p") String query, #RequestParam(value = "page", defaultValue = "0") int page, Pageable pageable) {
Criteria criteria = new Criteria();
final Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match( criteria.orOperator(
Criteria.where( "name" ).regex( query, "i" ),
Criteria.where( "details.brand" ).regex( query, "i" ),
Criteria.where( "details.tags.tags1" ).regex( query, "i" ),
Criteria.where( "details.tags.tags2" ).regex( query, "i" ),
Criteria.where( "details.tags.tags3" ).regex( query, "i" )
)),
Aggregation.skip(page * 4),
Aggregation.limit(4)
);
List<Products> filter = mongoTemplate.aggregate(aggregation, "Product", Products.class).getMappedResults();
return new PageImpl<Products>(filter, pageable, filter.size());
}
Mongodb 3.4 has introduced $facet aggregation which processes multiple aggregation pipelines within a single stage on the same set of input documents.
Using $facet and $group you can find documents with $limit and can get total count.
You can use below aggregation in mongodb 3.6
db.collection.aggregate([
{ "$facet": {
"totalData": [
{ "$match": { }},
{ "$skip": 10 },
{ "$limit": 10 }
],
"totalCount": [
{ "$count": "count" }
]
}}
])

How to perform elastic search _update_by_query using painless script - for complex condition

Can you suggest how to update documents (with a script - i guess painless) that based on condition fields?
its purpose is to add/or remove values from the document
so if I have those input documents:
doc //1st
{
"Tags":["foo"],
"flag":"true"
}
doc //2nd
{
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
And I want to perform something like this:
Update all documents that have "flag=true" with:
Added tags: "me", "one"
Deleted tags: "goo","foo"
so expected result should be something like:
doc //1st
{
"Tags":["me","one"],
"flag":"true"
}
doc //2nd
{
"Tags":["me","one"],
"flag":"true"
}
doc //3rd
{
"Tags": ["goo"],
"flag":"false"
}
Create mapping:
PUT documents
{
"mappings": {
"document": {
"properties": {
"tags": {
"type": "keyword",
"index": "not_analyzed"
},
"flag": {
"type": "boolean"
}
}
}
}
}
Insert first doc:
PUT documents/document/1
{
"tags":["foo"],
"flag": true
}
Insert second doc (keep in mind that for empty tags I specified empty tags array because if you don't have field at all you will need to check in script does field exists):
PUT documents/document/2
{
"tags": [],
"flag": true
}
Add third doc:
PUT documents/document/3
{
"tags": ["goo"],
"flag": false
}
And then run _update_by_query which has two arrays as params one for elements to add and one for elements to remove:
POST documents/_update_by_query
{
"script": {
"inline": "for(int i = 0; i < params.add_tags.size(); i++) { if(!ctx._source.tags.contains(params.add_tags[i].value)) { ctx._source.tags.add(params.add_tags[i].value)}} for(int i = 0; i < params.remove_tags.size(); i++) { if(ctx._source.tags.contains(params.remove_tags[i].value)){ctx._source.tags.removeAll(Collections.singleton(params.remove_tags[i].value))}}",
"params": {
"add_tags": [
{"value": "me"},
{"value": "one"}
],
"remove_tags": [
{"value": "goo"},
{"value": "foo"}
]
}
},
"query": {
"bool": {
"must": [
{"term": {"flag": true}}
]
}
}
}
If you then do following search:
GET documents/_search
you will get following result (which I think is what you want):
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [{
"_index": "documents",
"_type": "document",
"_id": "2",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "1",
"_score": 1,
"_source": {
"flag": true,
"tags": [
"me",
"one"
]
}
},
{
"_index": "documents",
"_type": "document",
"_id": "3",
"_score": 1,
"_source": {
"tags": [
"goo"
],
"flag": false
}
}
]
}
}

How to search exact text in nested document in elasticsearch

I have a index like this,
"_index": "test",
"_type": "products",
"_id": "URpYIFBAQRiPPu1BFOZiQg",
"_score": null,
"_source": {
"currency": null,
"colors": [],
"api": 1,
"sku": 9999227900050002,
"category_path": [
{
"id": "cat00000",
"name": "B1"
},
{
"id": "abcat0400000",
"name": "Cameras & Camcorders"
},
{
"id": "abcat0401000",
"name": "Digital Cameras"
},
{
"id": "abcat0401005",
"name": "Digital SLR Cameras"
},
{
"id": "pcmcat180400050006",
"name": "DSLR Package Deals"
}
],
"price": 1034.99,
"status": 1,
"description": null,
}
And i want to search only exact text ["Camcorders"] in category_path field.
I did some match query, but it search all the products which has "Camcorders" as a part of the text. Can some one help me to solve this.
Thanks
To search in nested field use like following query
{
"query": {
"term": {
"category_path.name": {
"value": "b1"
}
}
}
}
HOpe it helps..!
you could add one more nested field raw_name with not_analyzed analyzer and match against it.

Elasticsearch nested Query parseException

I get a parse exception when i want to get data out of my elastic search. My document looks like this
{
"_index": "some name",
"_type": "row",
"_id": "665",
"_score": 6.3700795,
"_source": {
"dateOfClaim": 1215986400000,
"employer": {
"username": null,
"password": null,
"name": "customer",
"customerNumber": "some number",
"dosierNumbers": null
},
"recipient": {
"username": null,
"password": null,
"name": "some name",
"taxNumber": "some number"
},
"claim": 402401,
"dosierNumber": "",
"worthWayTaxes": "",
"good": {
"brutoWeight": 25,
"nettoWeight": 25050,
"coll": 25000,
"taxWorth": "58830.67",
"eori": ""
},
"poDValues": "YES",
"correctedTaxNumber": null,
"note": null
}
},
and my query looks like this
POST /customs/_search
{
"nested" : {
"path" : "employer",
"score_mode" : "none",
"query" : {
"match": {
"employer.name" : "customer"
}
}
}
}
I want to get all document of a specific employer where the poDValue is NO. But my query already gives me a parseexception (All shards failed for phase: [query]) even without say that the poDValue should be NO.
I think you misunderstood the concept of nested objects. You are just using an object content, not nested object. Check this one:
POST /_search
{
"query": {
"term": {
"employer.titel": {
"value": "Dit is mijn titel"
}
}
}
}

Resources