One possibility is to use the completion suggester. It provides the "weight" that allows you to rank your suggestions.
Below I made an example that allows you to manipulate the order of suggestions. I hope it helps.
PUT idx_test
{
"mappings": {
"properties": {
"role": {
"type": "text"
},
"suggest": {
"type": "completion"
}
}
}
}
POST idx_test/_doc
{
"role":"Senior Software Engineer Assistant",
"suggest": [
{
"input": "Senior Software Engineer Assistant",
"weight": 50
},
{
"input": "Software Engineer Assistant",
"weight": 50
}
]
}
POST idx_test/_doc
{
"role":"Software Engineer Staff",
"suggest": [
{
"input": "Software Engineer Staff",
"weight": 40
}
]
}
POST idx_test/_doc
{
"role":"Software Engineer Group",
"suggest": [
{
"input": "Software Engineer Group",
"weight": 20
}
]
}
POST idx_test/_doc
{
"role":"Software Engineer",
"suggest": [
{
"input": "Software Engineer",
"weight": 10
}
]
}
GET idx_test/_search
{
"suggest": {
"role-suggest": {
"prefix": "software engg",
"completion": {
"field": "suggest",
"fuzzy": {
"fuzziness": 2
}
}
}
}
}
Results:
{
"suggest": {
"role-suggest": [
{
"options": [
{
"_source": {
"role": "Senior Software Engineer Assistant",
"suggest": [
{
"input": "Senior Software Engineer Assistant",
"weight": 50
},
{
"input": "Software Engineer Assistant",
"weight": 50
}
]
}
},
{
"_source": {
"role": "Software Engineer Staff",
"suggest": [
{
"input": "Software Engineer Staff",
"weight": 40
}
]
}
},
{
"_source": {
"role": "Software Engineer Group",
"suggest": [
{
"input": "Software Engineer Group",
"weight": 20
}
]
}
},
{
"_source": {
"role": "Software Engineer",
"suggest": [
{
"input": "Software Engineer",
"weight": 10
}
]
}
}
]
}
]
}
}
I finally managed to create a query that does exactly what i wanted to have:
A filtered nested boolean query.
I am not sure why this is not documented. Maybe someone here can tell me?
Here is the query:
GET /test/object/_search
{
"from": 0,
"size": 20,
"sort": {
"_score": "desc"
},
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"state": 1
}
}
]
}
},
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"name": "foo"
}
},
{
"match": {
"name": "bar"
}
}
],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"info": "foo"
}
},
{
"match": {
"info": "bar"
}
}
],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
}
],
"minimum_should_match": 1
}
}
}
}
}
In pseudo-SQL:
SELECT * FROM /test/object
WHERE
((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1
Please keep in mind that it depends on your document field analysis and mappings how name=foo is internally handled. This can vary from a fuzzy to strict behavior.
"minimum_should_match": 1 says, that at least one of the should statements must be true.
This statements means that whenever there is a document in the resultset that contains has_image:1 it is boosted by factor 100. This changes result ordering.
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
Have fun guys :)