WhiteFangs
WhiteFangs

Reputation: 704

Get an output different from input with elasticsearch completion suggester

I recently upgraded from Elasticsearch 1.4 to 5.4 and I'm struggling to migrate my autocomplete queries efficiently. The problem is that I want to have a completion suggester where the output is different from the input.

The documents I store have a field for categories which is basically an array of strings with their URIs (because they form a tree). The last part of the URI, I call it label, is the input in the completion suggester, but as a response I would like to retrieve the full URI.

So let's say I have two documents:

{
    "name" : "Lord of The Rings",
    "categories" : ["Books/Genre/Fantasy", "Books/Language/English"]
}

and

{
    "name" : "Game of Thrones",
    "categories" : ["Series/Genre/Fantasy", "Series/Host/HBO"]
}

My input is "Fant" and I want to get as a response the URIs for the "Series/Genre/Fantasy" and "Books/Genre/Fantasy" categories.

Previously with ES 1.4, I was able to create a completion suggester with a different output for a given input, so I indexed my suggesters like this:

{
    "suggest" : {
        "input": [ "Fantasy"],
        "output": "Series/Genre/Fantasy"
    }
}

and

{
    "suggest" : {
        "input": [ "Fantasy"],
        "output": "Books/Genre/Fantasy"
    }
}

But in ES 5.4, the output property doesn't exist anymore for completion suggesters so all I get in the response is the input property of my suggest field, which is the label "Fantasy", but I want the URI.

Right now, my workaround is to look for the categories field of each document returned in the _source property of the response, and filter on the categories that have a label starting with the input "Fant". It is very inefficient since I need to map every category of every returned document into its label to check with the input.

Isn't there a more efficient way to do that with ES suggesters? What am I missing?

Upvotes: 4

Views: 1411

Answers (1)

mayankchutani
mayankchutani

Reputation: 281

Elasticsearch's completion suggester have been changed from 5.0. The support for specifying output when indexing suggestion entries has been removed. Now suggestion result entry’s text is always the un-analyzed value of the suggestion’s input (same as not specifying output while indexing suggestions in pre-5.0 indices). So you need to add output as a sibling field of suggest key in the body.
Here's how it should look like:

Mapping:

{
    "mappings": {
        "<type>" : {
            "properties" : {
                "suggest" : {
                    "type" : "completion"
                },
                "output" : {
                    "type": "keyword"
                }
            } 
        }
    }
}

Don't forget to replace <type> with your index type.

Indexing:

/<index_name>/<type_name>

{
    "suggest" : {
        "input": ["Fantasy"],
        "weight" : 1
    },
    "output": "Series/Genre/Fantasy"
}

Here, the field name output can be replaced by anything, it's just meta-data of your document.

Query:

/<index_name>/_search

{
    "suggest": {
        "show-suggest" : {
            "prefix" : "Fant",
            "completion" : {
                "field" : "suggest"
            }
        }
    }
}

I hope this helps.

Upvotes: 6

Related Questions