2

How would you search an index in Elastic Search that would include different matching indexes/entities along with it. I need to have complex search suggestions, they need to be grouped per entity. An image speaks a thousand words, so the following image describes pretty much what I want to achieve:

Advanced search

How should I model my indexes to achieve the above?

Right now my order index looks like this:

{
    "_index": "mango",
    "_type": "order",
    "_id": "4",
    "_score": 1,
    "_source": {
    "number": "000000004",
    "customer": {
        "id": 14,
        "firstName": "Jean",
        "lastName": "Hermann",
        "email": "lucinda90@example.com"
        }
    }
}

And when I do a search with the text example.com I need a response, that looks somewhat like (left out hits to be more readable):

{
  "hits": {
    "hits": []
  }
  "aggregations": {
    "customers": [
        {
            "id": 1,
            "firstName": "Mille",
            "lastName": "VonRueden",
            "email": "shickle@example.com"
        },
        {
            "id": 2,
            "firstName": "Clint",
            "lastName": "Effertz",
            "email": "briana91@example.com"
        }
    ]
  }
}

How would my search query look like to achieve such response?

I have tried to use the following search query, but it just returns an empty bucket:

{
    "size": 1,
    "aggs": {
        "customers": {
            "nested": {
                "path": "customer"
            },
            "aggs": {
                "name": {
                    "terms": {
                        "field": "customer.id"
                    }
                }
            }
        }
    }
}

This is the mapping of my order index (in YAML format):

order:
    mappings:
        number: ~
        createdAt:
            type: date
        customer:
            type: nested
            properties:
                id :
                    type : integer
                    index: not_analyzed
                firstName:
                    type: string
                    index: not_analyzed
Steffen Brem
  • 1,738
  • 18
  • 29

1 Answers1

0

The easiest would be to have one index and mapping type per entity. The screenshot you are showing could be modeled like this:

  • index: companies and mapping type company
  • index: groups and mapping type group
  • index: features and mapping type feature
  • index: skills and mapping type skill

Here are some sample commands you'd use to create those indices and mapping types for each of the entities:

curl -XPUT localhost:9200/companies -d '{
    "mappings": {
        "company": { "properties": { ... }}
    }
}'
curl -XPUT localhost:9200/groups -d '{
    "mappings": {
        "group": { "properties": { ... }}
    }
}'
curl -XPUT localhost:9200/features -d '{
    "mappings": {
        "feature": { "properties": { ... }}
    }
}'
curl -XPUT localhost:9200/skills -d '{
    "mappings": {
        "skill": { "properties": { ... }}
    }
}'

Then when searching, you'd need to search on all indices and mapping types and order the results by _type (asc) and _score (desc):

curl -XPOST 'localhost:9200/_search?q=blog' -d '{
    "sort":[
        {"_type":"asc"},
        {"_score":"desc"}
    ]
}'

Finally, you simply need to read your sorted results and show them according to their type.

UPDATE

Following up on your comments, if you wish to do it through aggregations, you're on the right path, you'd just need to add a top_hits sub-aggregation:

{
    "size": 1,
    "aggs": {
        "customers": {
            "nested": {
                "path": "customer"
            },
            "aggs": {
                "name": {
                    "terms": {
                        "field": "customer.id"
                    },
                    "aggs": {               <--- add this
                        "hits": {
                             "top_hits: {}
                        }
                    }
                }
            }
        }
    }
}
Val
  • 207,596
  • 13
  • 358
  • 360
  • Can't this be achieved with aggregations or something? I would not like to mix the different indices in `hits`, but rather have them as meta data. Something like filtered aggregations based on the given search query. Not sure if that makes sense, I am quite new to ES. – Steffen Brem Jan 17 '16 at 14:12
  • I've updated my question to give an example of how my current index looks like. Also included an expected response, do you maybe know how I would need to search to have enough information (like first name etc.) in my `customers` aggregation? – Steffen Brem Jan 17 '16 at 14:56
  • I've updated my answer, please give it a try and see how it goes. – Val Jan 17 '16 at 16:20
  • Thanks for helping me out, but it does not seem to return any buckets either. Maybe it is my mapping, i've added my mapping of the `order` index as YAML in my question. – Steffen Brem Jan 17 '16 at 16:24