5

I'm using elasticsearch (v2.0.0) for search in Rails and want to add to our custom script for scoring, but I'm either messing up the syntax or just missing something else entirely. It all works without the check in the script for the array, so that's the only part that's not working.

So for the index, recipe_user_ids is an array of integers:

indexes :recipe_user_ids, type: 'integer'

Then in the search query I specify the parameter for the script file and which script file:

functions: [{
  script_score: {
    params: { current_user_id: user.id },
    script_file: 'ownership_script'
  }
}]

And the ownership-script.groovy file:

if (current_user_id == doc['user_id'].value) { owner_modifier = 1.0 } else { owner_modifier = 0.0 }
if (doc['recipe_user_ids'].values.contains(current_user_id)) { recipe_user_modifier = 50.0 } else { recipe_user_modifier = 0.0 }
(_score + (doc['score_for_sort'].value + owner_modifier + recipe_user_modifier)*5)/_score

I'm not getting any errors, but the results don't seem to match what I'd expect when the recipe_user_ids array does contain current_user_id, so everything is falling into the else statement. Is it a type issue, syntax? Any tips greatly appreciated.

4
  • What is the correct name of that field: recipes_user_ids or recipe_user_ids ? You have both names in there... Commented Sep 1, 2016 at 3:54
  • Sorry, that was a typo in the post, not the code! Edited. Commented Sep 1, 2016 at 3:56
  • Where does the user.id value come from in your script parameters? And what version of ES are you running? Commented Sep 1, 2016 at 3:57
  • It's just an integer id from the user model. ES 2.0.0. Commented Sep 1, 2016 at 14:38

1 Answer 1

1
+50

This seems to occur due to mismatch in type caused by autoboxing.

The doc['field_name].values for field mapping short, integer, long types seems to be returning a collection always of type 'Long' and the argument to contains is autoboxed to Integercausing contains to fail.

You could probably explictly cast current_user_id to the type of Long:

Example:

doc['recipe_user_ids'].values.contains(new Long(current_user_id))

Or better to use the 'find' method

doc['recipe_user_ids'].values.find {it == current_user_id}

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

8 Comments

I think you need to remove the parenthesis around the find closure.
@Val strange works for me ! what error is it throwing ?
you can keep the (...), but it's not necessary in groovy
should be .find{it == current_user_id}
don't think it is faster but i don't think it would be perceptibly slower. The reason i feel find is better since it does not invole an explicit cast . Casting the parameter to Long is an implementation detail and may fail if in future upgrades of es changes values to return a type other than Long collection.
|

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.