2014-12-03 12 views
6

Ho avuto a che fare con questo problema da un po 'di tempo e non riesco a risolvere il problema.Query con punteggio funzione con field_value_factor su campo non ancora esistente

Prendete il caso seguente:

Ho 2 dipendenti nella mia azienda che hanno una propria pagina blog:

POST blog/page/1 
{ 
    "author": "Byron", 
    "author-title": "Junior Software Developer", 
    "content" : "My amazing bio" 
} 

e

POST blog/page/2 
{ 
    "author": "Jason", 
    "author-title": "Senior Software Developer", 
    "content" : "My amazing bio is better" 
} 

Dopo aver creato i loro post del blog, abbiamo vorrebbe tenere traccia dei "punti di vista" dei propri blog e aumentare i risultati di ricerca in base alle loro "viste".

questo può essere fatto utilizzando la function score query:

GET blog/_search 
{ 
    "query": { 
    "function_score": { 
     "query": { 
     "match": { 
      "author-title": "developer" 
     } 
     }, 
     "functions": [ 
     { 
      "filter": { 
      "range": { 
       "views": { 
       "from": 1 
       } 
      } 
      }, 
      "field_value_factor": { 
      "field": "views" 
      } 
     } 
     ] 
    } 
    } 
} 

Io uso il filtro gamma per assicurarsi che il field_value_factor non influisce sul punteggio quando la quantità di punti di vista è 0 (punteggio sarebbe anche 0).

Ora, quando provo a fare funzionare questa domanda, mi metterò la seguente eccezione:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }] 

che ha un senso, perché il campo non esiste da nessuna parte nell'indice. Se dovessi aggiungere views = 0 all'ora dell'indice, non avrei il problema sopra visto che il campo è noto all'interno dell'indice. Ma nel mio caso d'uso non riesco ad aggiungere questo su index-time o su una mappatura.

In base alla possibilità di utilizzare un filtro intervallo all'interno della query del punteggio funzione, ho pensato che sarei stato in grado di utilizzare uno exists filter per assicurarsi che la parte field_value_factor sarebbe stata eseguita solo quando il campo è effettivamente presente nell'indice, ma senza fortuna del genere:

GET blog/_search 
{ 
    "query": { 
    "function_score": { 
     "query": { 
     "match": { 
      "author-title": "developer" 
     } 
     }, 
     "functions": [ 
     { 
      "filter": { 
      "bool": { 
       "must": [ 
       { 
        "exists": { 
        "field": "views" 
        } 
       }, 
       { 
        "range": { 
        "views": { 
         "from": 1 
        } 
        } 
       } 
       ] 
      } 
      }, 
      "field_value_factor": { 
      "field": "views" 
      } 
     } 
     ] 
    } 
    } 
} 

dà ancora:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }] 

Dove mi aspetto elasticsearch per applicare il filtro, prima l'analisi del field_value_factor.

Qualche idea su come risolvere questo problema, senza l'utilizzo di file di mapping o di correzione durante l'indice o gli script ??

+0

Sto riscontrando lo stesso problema al momento. Sei stato in grado di trovare una soluzione per questo? – tschubotz

+0

Questo ha un baco qui: https://github.com/elastic/elasticsearch/issues/10948 – OrangeDog

risposta

3

L'errore che si sta verificando si verifica al momento dell'analisi delle query, ovvero non è stato ancora eseguito nulla. A quel tempo, FieldValueFactorFunctionParser crea la funzione filter_value_factor da eseguire in un secondo momento, ma nota che il campo views non esiste nel tipo di mapping.

Si noti che il filtro non è stato ancora eseguito, proprio come la funzione filter_value_factor, è stato analizzato solo da FunctionScoreQueryParser.

mi chiedo perché non si può semplicemente aggiungere un campo nel vostro tipo di mappatura, è facile quanto l'esecuzione di questo

curl -XPUT 'http://localhost:9200/blog/_mapping/page' -d '{ 
    "page" : { 
     "properties" : { 
      "views" : {"type" : "integer"} 
     } 
    } 
}' 

Se questo non è realmente un'opzione, un'altra possibilità sarebbe quella di utilizzare script_score invece, in questo modo:

{ 
    "query": { 
    "function_score": { 
     "query": { 
     "match": { 
      "author-title": "developer" 
     } 
     }, 
     "functions": [ 
     { 
      "filter": { 
      "range": { 
       "views": { 
       "from": 1 
       } 
      } 
      }, 
      "script_score": { 
      "script": "_score * doc.views.value" 
      } 
     } 
     ] 
    } 
    } 
}