С ElasticSearch сортировать по данному массиву - PullRequest
0 голосов
/ 01 октября 2018

Я храню в ElasticRearch серию каналов.Каждый канал имеет актера, публикующего такой канал и дату публикации.В другом месте я сохраняю взвешенное значение для каждого участника следующим образом:

weights: [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]

Мне нужно запросить каналы, сгруппированные по дате, но упорядоченные по таким весам.Я попытался сделать функцию сортировки, используя безболезненно, но я застрял в определении весов:

{
    "size": 0,
    "query": {
        "bool": {
            "should": [
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "actor.id": "mark"
                                }
                            },
                            {
                                "range": {
                                    "published": {"gte": "2017-09-30T15:37:21.530483"}
                                }
                            }
                        ]
                    }
                },
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "actor.id": "jane"
                                }
                            },
                            {
                                "range": {
                                    "published": {"gte": "2017-09-30T15:37:21.530483"}
                                }
                            }
                        ]
                    }
                }
            ]
        }
    },
    "aggs": {
        "dates": {
            "terms": {
                "field": "published_date",
            },
            "aggs": {
                "top_verbs_hits": {
                    "top_hits": {
                        "sort": {
                            "_script": {
                                "type": "number",
                                "script": {
                                    "lang": "painless",
                                    "source": "def weights = [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]; def weight = 0; for (int i = 0; i < weights.length; ++i) { if (weights[i].id == doc.actor.id) return weights[i].weight; } return weight;"
                                },
                                "order": "asc"
                            }
                        },
                        "_source": {
                            "includes": ["published", "actor", "object", "target", "extra"]
                        },
                        "size": 100
                    }
                }
            }
        }
    },
    "sort": [
        {
            "published": {
                "order": "desc"
            }
        }
    ],
}

Для ясности безболезненная функция выглядит следующим образом:

def weights = [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]; 
def weight = 0; 
for (int i = 0; i < weights.length; ++i) 
{ 
    if (weights[i].id == doc.actor.id) 
    return weights[i].weight; 
} 
return weight;

Упругие дать мнеошибка компиляции рядом с определением массива.Я предполагаю, что я не могу определить список / массив объектов JSON:

compile error","script_stack":["def weights = [{'id': 'mark', 'weight ...","               ^---- HERE"]....

Есть ли способ сделать это с помощью сценария сортировки или без него?

1 Ответ

0 голосов
/ 01 октября 2018

Безболезненный не похожий на javascript язык.Вы не можете просто определить массив с JSON-подобным синтаксисом.

Вы можете иметь полную документацию здесь для массива.Также у вас есть создать карту для представления ваших объектов JSON.

Но в вашем случае вы должны окончательно использовать параметры сценариев

Не могли бы вы попробовать что-то вроде:

"sort": {
    "_script": {
        "type": "number",
        "script": {
            "lang": "painless",
            "source": "def weight = 0; for (int i = 0; i < params.weights.length; ++i) { if (params.weights[i].id == doc['actor.id'].value) return params.weights[i].weight; } return weight;"
            "params": {
              "weights" :[{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]
            } 
        },
        "order": "asc"
    }
}

Используя параметры, вы можете определитьваши входные данные с синтаксисом JSON И, кроме того, вы разрешаетеasticsearch кэшировать скомпилированную версию вашего скрипта, так как источник останется прежним, даже если массив весов изменится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...