2

I have a working Elasticsearch query which looks like this:

{
    "index": "event",
    "type": "item",
    "body": {
        "query": {
            "filtered": {
                "query": {
                    "multi_match": {
                        "query": "party",
                        "type": "phrase_prefix",
                        "fuzziness": null,
                        "fields": [
                            "label^2",
                            "excerpt",
                            "body"
                        ]
                    }
                },
                "filter": {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "is_deleted": false
                                }
                            },
                            {
                                "term": {
                                    "is_private": false
                                }
                            },
                            {
                                "range": {
                                    "date_start": {
                                        "gt": "now"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
}

This query searches for events which match the keyword search, are due to start in the future and filters out any marked as deleted or private.

Each user who can create an event can also buy a package to the system. I'd like to boost users whose package is of a higher value. I'm sure I need to implement a custom scoring funciton using Function Score Query, but I can't get my head around the docs and blindly trying it isn't getting me anywhere.

As an example, indexed docs might look like this:

[
    {
        "label": "My Birthday Party",
        "excerpt": "Come celebrate with me as I turn 30",
        "body": "I'm turning 30 soon, let's go dancing!",
        "date_start": "2016-06-19",
        "is_deleted": false,
        "is_private": false,
        "user": {
            "id": 1,
            "name": "Pablo",
            "package": {
                "id": 14,
                "cost": "1000",
                "label": "The \"£10 per month\" package"
            }
        }
    },
    {
        "label": "House Warming Party",
        "excerpt": "I moved house, help me decorate it",
        "body": "I love my new house, but it's empty and I have no furniture.",
        "date_start": "2016-04-19",
        "is_deleted": false,
        "is_private": false,
        "user": {
            "id": 2,
            "name": "Gary",
            "package": {
                "id": 15,
                "cost": "5000",
                "label": "The \"£50 per month\" package"
            }
        }
    }
]

In a query which returned both of these results, how might I prioritise poor Gary (who needs help decorating) over Pablo's birthday, based on the fact that Gary's package is of a higher value (i.e. user.package.cost).

In an otherwise equal search, Gary's result must come first.

Any pointers?

Thanks.

1 Answer 1

2

Use script score to achieve this.

 "query": {
  "function_score": {
     "query": {
        "match_all": {}
     },
     "functions": [
        {
           "script_score": {
              "script": "_score * doc['user.package.cost'].value"

           }
        }
       ]
    }
 }

Hope it helps..

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @richa - set me on the right track! Needed to enable [groovy] searches, but once I worked that out I got it working well.
I'm struggling to write an appropriate script which first checks if user.package exists (it can be null for a user with no package). Variations of packageCost = doc['user.package'].value ? doc['user.package.cost'].value : 1; return packageCost * _score give me [not so] groovy errors - any pointers?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.