Elasticsearch custom sorting / adding filter clauses scores -
i have simple documents set:
{ id : 1, book_ids : [2,3], collection_ids : ['a','b'] }, { id : 2, book_ids : [1,2] } if run filter query, match both documents:
{ bool: { filter: [ { bool: { should: [ { bool: { must_not: { exists: { field: 'book_ids' } } } }, { bool: { filter: { term: { book_ids: 2 } } } } ] } }, { bool: { should: [ { bool: { must_not: { exists: { field: 'collection_ids' } } } }, { bool: { filter: { term: { collection_ids: 'a' } } } } ] } } ] } } the thing want sort these documents, , first 1 (id: 1) returned first because matched both book_ids value , collection_ids values provided.
a simple sort clause 1 not working:
[ 'book_ids', 'collection_ids' ] because return first document 2 due book_ids array first value.
edit: simplified example of problem facing, has n such clauses in should clause. there order between clauses, tried reflect sort snippet: results matching first clause (book_ids) should appear before results matching second clause (collection_ids). looking kind of sql sort operation take account matching value of field array. viable option might assign decreasing constant_scores each term clause, according expected sort order, , es have sum sub-scores compute final score. cannot figure out how or if possible.
bonus question: there way elasticsearch return kind of new document matching values? here expect response above filter query:
{ id : 1, book_ids : [2], collection_ids : ['a'] }, { id : 2, book_ids : [2] }
i think you're right constant score idea. think can this:
{ query: { bool: { must: [ { bool: { should: [ { bool: { must_not: { exists: { field: 'book_ids' } } } }, { constant_score: { filter: { term: { book_ids: 2 } }, boost: 100 } } ] } }, { bool: { should: [ { bool: { must_not: { exists: { field: 'collection_ids' } } } }, { constant_score: { filter: { term: { collection_ids: 'a' } }, boost: 50 } } ] } } ] } } } i think thing missing using constant score, top level query needs must, not filter. (there's no scoring filters, scores 0.)
an alternative put filter inside function_score query (but leave filter), , compute score want (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html)
as bonus question, it's possible if use script field filter , add new field want (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html), it's not possible in straightforward way. it's easier , makes more sense filtering after receive result, unless have long lists in values.
Comments
Post a Comment