Assistance with Choosing the Correct Query Structure

Hi All,

TL;DR: Doing dynamic currency conversion via function_score works great for
scenarios where I want to sort by prices,
but I want the same functionality in queries that will be sorted by
relevance score when using terms while still retaining
a dynamically calulated field for converted price.

Long version:

I'm looking to deploy Elasticsearch as a primary search engine for a
catalog of products. Each product has a
provider_price and provider_currency field. The "provider_price" is always
in the currency specified by
"provider_currency". When a user gets their search results they want to
display it in their local currency. To
do this I've come up with two different queries depending on how the
results will be sorted for the end user.

  1. If the user requests a price-based sorting (asc/desc) then I'm using a
    function_score query like so:

{
"query": {
"function_score": {
"functions": [
"script_score": {
"script": "( rates[_source.provider_currency] *
_source.provider_price )",
"params": {
"rates": {
"USD": 1,
"AUD": 0.75,
...
...
...
}
}
}
],
"query": {
"filtered": {
........
}
}
},
"sort": {
{
"_score": "asc/desc"
}
}
}

  1. When sorting by terms or other fields in the document I still need to
    calculate the converted price, so I'm using script_fields like so:

{
"fields": [
"_source"
],
"query": {
......
},
"script_fields": {
"user_price": {
"script": "( rates[_source.provider_currency] *
_source.provider_price )",
"params": {
"rates": {
"USD": 1,
"AUD": 0.75,
...
...
...
}
}
}
},
"sort": [
{
"_score": "desc"
}
]
}

A few queries with the above:

  1. Does this generally seem like a sane implementation?

  2. These both work perfectly for doing on-the-fly conversions of currency
    and returing it with the documents,
    but at the moment my app-side code has to make the distinction
    between price-sorting queries and term
    queries and issue the correct one, as well extract the converted
    price from the correct field depending
    (_score or _source.user_price respectively).

    Is there any way to simplify this?

    e.g. When doing a function_score query, copy the _score to another
    generated field called "user_score".
    That way the code only needs to know about one field ("user_score")
    for both queries.

Cheers for any assistance the community can provide.

David.

--
You received this message because you are subscribed to the Google Groups "elasticsearch" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elasticsearch+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elasticsearch/aef94d97-dad6-43c4-866f-af749101ce6a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sorry, I missed out "boost_mode": "replace" in my function_score example
above. I want the score to be the exact converted
currency, so I can make use of it in code.

On Thursday, April 16, 2015 at 10:44:35 AM UTC+1, David Dyball wrote:

Hi All,

TL;DR: Doing dynamic currency conversion via function_score works great
for scenarios where I want to sort by prices,
but I want the same functionality in queries that will be sorted by
relevance score when using terms while still retaining
a dynamically calulated field for converted price.

Long version:

I'm looking to deploy Elasticsearch as a primary search engine for a
catalog of products. Each product has a
provider_price and provider_currency field. The "provider_price" is
always in the currency specified by
"provider_currency". When a user gets their search results they want to
display it in their local currency. To
do this I've come up with two different queries depending on how the
results will be sorted for the end user.

  1. If the user requests a price-based sorting (asc/desc) then I'm using a
    function_score query like so:

{
"query": {
"function_score": {
"functions": [
"script_score": {
"script": "( rates[_source.provider_currency] *
_source.provider_price )",
"params": {
"rates": {
"USD": 1,
"AUD": 0.75,
...
...
...
}
}
}
],
"query": {
"filtered": {
........
}
}
},
"sort": {
{
"_score": "asc/desc"
}
}
}

  1. When sorting by terms or other fields in the document I still need to
    calculate the converted price, so I'm using script_fields like so:

{
"fields": [
"_source"
],
"query": {
......
},
"script_fields": {
"user_price": {
"script": "( rates[_source.provider_currency] *
_source.provider_price )",
"params": {
"rates": {
"USD": 1,
"AUD": 0.75,
...
...
...
}
}
}
},
"sort": [
{
"_score": "desc"
}
]
}

A few queries with the above:

  1. Does this generally seem like a sane implementation?

  2. These both work perfectly for doing on-the-fly conversions of
    currency and returing it with the documents,
    but at the moment my app-side code has to make the distinction
    between price-sorting queries and term
    queries and issue the correct one, as well extract the converted
    price from the correct field depending
    (_score or _source.user_price respectively).

    Is there any way to simplify this?

    e.g. When doing a function_score query, copy the _score to another
    generated field called "user_score".
    That way the code only needs to know about one field ("user_score")
    for both queries.

Cheers for any assistance the community can provide.

David.

--
You received this message because you are subscribed to the Google Groups "elasticsearch" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elasticsearch+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elasticsearch/4fcdbf81-a081-4eb9-a292-35a506ee9c65%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.