J'essaie de créer un script en utilisant le script_score
du function_score
. J'ai plusieurs documents dont le champ rankings
est type="nested"
. Le mappage de ce champ est le suivant:
"rankings": {
"type": "nested",
"properties": {
"rank1": {
"type": "long"
},
"rank2": {
"type": "float"
},
"subject": {
"type": "text"
}
}
}
Un exemple de document est:
"rankings": [
{
"rank1": 1051,
"rank2": 78.5,
"subject": "s1"
},
{
"rank1": 45,
"rank2": 34.7,
"subject": "s2"
}]
Ce que je veux réaliser est de parcourir les objets imbriqués du classement. En fait, j’ai besoin d’utiliser une boucle for pour trouver un subject
particulier et utiliser le rank1, rank2
pour calculer quelque chose . Jusqu’à présent, j’utilise quelque chose comme ceci mais cela ne semble pas fonctionner (en générant une erreur Compile):
"function_score": {
"script_score": {
"script": {
"lang": "painless",
"inline":
"sum = 0;"
"for (item in doc['rankings_cug']) {"
"sum = sum + doc['rankings_cug.rank1'].value;"
"}"
}
}
}
J'ai aussi essayé les options suivantes:
for
utilisant :
au lieu de in
: for (item:doc['rankings'])
sans succès.for
utilisant in
mais en essayant de parcourir un élément spécifique de l'objet, c'est-à-dire le rank1
: for (item in doc['rankings.rank1'].values)
, qui compile réellement, mais il semble qu'il trouve un tableau de longueur nulle de rank1
.J'ai lu que l'élément _source
est celui qui peut renvoyer des objets de type JSON, mais d'après ce que j'ai découvert, il n'est pas pris en charge dans les requêtes de recherche.
Pouvez-vous me donner quelques idées sur la manière de procéder?
Merci beaucoup.
Vous pouvez accéder à _source via params._source
. Celui-ci fonctionnera:
PUT /rankings/result/1?refresh
{
"rankings": [
{
"rank1": 1051,
"rank2": 78.5,
"subject": "s1"
},
{
"rank1": 45,
"rank2": 34.7,
"subject": "s2"
}
]
}
POST rankings/_search
POST rankings/_search
{
"query": {
"match": {
"_id": "1"
}
},
"script_fields": {
"script_score": {
"script": {
"lang": "painless",
"inline": "double sum = 0.0; for (item in params._source.rankings) { sum += item.rank2; } return sum;"
}
}
}
}
DELETE rankings
Malheureusement, les scripts ElasticSearch en général ne permettent pas d'accéder aux documents imbriqués de cette manière (y compris à l'indolore). Envisagez peut-être une structure différente de vos mappages, dans laquelle les classements sont stockés dans des champs à valeurs multiples si vous devez pouvoir les parcourir de cette manière. En fin de compte, les données imbriquées devront être dé-normalisées et placées dans les documents parents pour pouvoir obtenir des scores de la manière décrite ici.
Pour les objets imbriqués dans un tableau, itérés sur les éléments et cela a fonctionné ... Voici mon exemple de données dans elasticsearch index:
{
"_index": "activity_index",
"_type": "log",
"_id": "AVjx0UTvgHp45Y_tQP6z",
"_version": 4,
"found": true,
"_source": {
"updated": "2016-12-11T22:56:13.548641",
"task_log": [
{
"week_end_date": "2016-12-11",
"log_hours": 16,
"week_start_date": "2016-12-05"
},
{
"week_start_date": "2016-03-21",
"log_hours": 0,
"week_end_date": "2016-03-27"
},
{
"week_start_date": "2016-04-24",
"log_hours": 0,
"week_end_date": "2016-04-30"
}
],
"created": "2016-12-11T22:56:13.548635",
"userid": 895,
"misc": {
},
"current": false,
"taskid": 1023829
}
}
Voici le script "indolore" pour parcourir les objets imbriqués:
{
"script": {
"lang": "painless",
"inline":
"boolean contains(def x, def y) {
for (item in x) {
if (item['week_start_date'] == y){
return true
}
}
return false
}
if(!contains(ctx._source.task_log, params.start_time_param) {
ctx._source.task_log.add(params.week_object)
}",
"params": {
"start_time_param": "2016-04-24",
"week_object": {
"week_start_date": "2016-04-24",
"week_end_date": "2016-04-30",
"log_hours": 0
}
}
}
}
Script utilisé ci-dessus pour la mise à jour: /activity_index/log/AVjx0UTvgHp45Y_tQP6z/_update Dans le script, a créé une fonction appelée "contient" avec deux arguments. Appelé la fonction . L'ancien style groovy: ctx._source.task_log.contains () ne fonctionnera pas car ES 5.X stocke les objets imbriqués dans un document séparé. J'espère que ça aide!