Since Elasticsearch doesn't support joins that well and in extension Kibana aswell I would recommend you to join the documents in your application before putting the documents in the index. If this is not a possibility I would go for a transformation as recommended in:
https://discuss.elastic.co/t/combine-multiple-document-into-one-document-with-limited-fields-merging-of-documents/231758
Using this I could achieve something like this in my dashboard:
Result image
Steps to reproduce:
- Create log index
PUT log_index
- Add some data
POST log_index/_doc/ {"id": "1", "field1": "The"}
POST log_index/_doc/ {"id": "1", "field2": "quick"}
POST log_index/_doc/ {"id": "1", "field3": "brown", "field4": "fox"}
POST log_index/_doc/ {"id": "2", "field1": "jumped"}
POST log_index/_doc/ {"id": "2", "field2": "over"}
POST log_index/_doc/ {"id": "2", "field3": "the"}
POST log_index/_doc/ {"id": "2", "field4": "lazy"}
- Transform the log index into a joined index (I'm pretty sure the scripted metric can be written better. This was the first thing that worked):
PUT _transform/join_logs
{
"source": {
"index": [
"log_index"
]
},
"pivot": {
"group_by": {
"id.keyword": {
"terms": {
"field": "id.keyword"
}
}
},
"aggregations": {
"field1": {
"scripted_metric": {
"init_script": "state.docs = []",
"map_script": "state.docs.add(new HashMap(params['_source']))",
"combine_script": "for (t in state.docs) { if(t.get('field1') != null){ return t.get('field1')}} return null",
"reduce_script": "states"
}
},
"field2": {
"scripted_metric": {
"init_script": "state.docs = []",
"map_script": "state.docs.add(new HashMap(params['_source']))",
"combine_script": "for (t in state.docs) { if(t.get('field2') != null){ return t.get('field2')}} return null",
"reduce_script": "states"
}
},
"field3": {
"scripted_metric": {
"init_script": "state.docs = []",
"map_script": "state.docs.add(new HashMap(params['_source']))",
"combine_script": "for (t in state.docs) { if(t.get('field3') != null){ return t.get('field3')}} return null",
"reduce_script": "states"
}
},
"field4": {
"scripted_metric": {
"init_script": "state.docs = []",
"map_script": "state.docs.add(new HashMap(params['_source']))",
"combine_script": "for (t in state.docs) { if(t.get('field4') != null){ return t.get('field4')}} return null",
"reduce_script": "states"
}
}
}
},
"dest": {
"index": "joined_index"
}
}
- Run the transformation
- Create index pattern for the join index
- Open up in discover and create table. Save it and add it to the dashboard.
My assumptions doing this was that the fields only occur once in each document with specified id. Don't know what happens if fields overlap between the documents.