Агрегация в arangodb с использованием AQL

Я пытаюсь выполнить довольно простую задачу в arangodb, используя агрегатную функцию SUM ().

Вот рабочий запрос, который возвращает правильные данные (хотя и не агрегированные):

FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : g[*].m[*].items }

Это возвращает следующие результаты:

[
  {
    "memberId": "40289",
    "amount": [
      [
        {
          "amount": 50,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 50,
          "description": "some description"
        },
        {
          "amount": 500,
          "description": "some description"
        },
        {
          "amount": 0,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 0,
          "description": "some description"
        },
      ]
    ]
  }
]

Я использую Collect для группировки результатов, потому что данный memberId может иметь несколько объектов RegMem. Как видно из запроса / результатов, каждый объект имеет список более мелких объектов, называемых «элементами», причем каждый элемент имеет количество и описание.

Я хочу СУММАТЬ () суммы по участникам. Однако такая настройка запроса не работает:

FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g
RETURN { "memberId" : member, "amount" : SUM(g[*].m[*].items[*].amount) }

Он возвращает 0, потому что, по-видимому, он не может найти поле с именем amount в развернутом списке элементов.

Глядя на результаты, я могу понять, почему: результаты возвращаются так, что items на самом деле является списком, состоящим из списков объектов с количеством / описанием. Но я не понимаю, как правильно ссылаться или расширять безымянный список, чтобы вернуть значения поля суммы для функции SUM ().

В идеале запрос должен возвращать memberId и общую сумму, по одной строке на член, чтобы я мог удалить фильтр и выполнить его для всех членов.

Заранее большое спасибо, если вы можете помочь! Мартин

PS Я проработал учебник AQL на веб-сайте arangodb и проверил руководство, но что действительно могло мне помочь, так это загрузка большего количества примеров запросов для просмотра. Если кто-то знает о подобном ресурсе или хочет поделиться своими собственными, очень признателен. Ваше здоровье!


person Martin    schedule 09.06.2014    source источник


Ответы (1)


Отредактировано: неправильно прочитал вопрос в первый раз. Первый можно увидеть в историиedit, так как он также содержит подсказки:

Я скопировал ваши данные, создав некоторые документы в этом формате (а некоторые только с одним элементом):

{
  "memberId": "40289",
  "items": [
    {
      "amount": 50,
      "description": "some description"
    },
    {
      "amount": 500,
      "description": "some description"
    }
  ]
}

Основываясь на некоторых из этих типов документов, ваш необобщенный запрос действительно должен выглядеть следующим образом:

FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g

RETURN { "memberId" : member, "amount" :  g[*].m[*].items }

Возвращенные данные:

[
  {
    "memberId": "40289",
    "amount": [
      [
        {
          "amount": 50,
          "description": "some description"
        },
        {
          "amount": 0,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 50,
          "description": "some description"
        },
        {
          "amount": 0,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 50,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 50,
          "description": "some description"
        },
        {
          "amount": 500,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 0,
          "description": "some description"
        }
      ],
      [
        {
          "amount": 50,
          "description": "some description"
        },
        {
          "amount": 500,
          "description": "some description"
        }
      ]
    ]
  }
]

Основываясь на несводной версии, вам нужно перебрать элементы групп, которые были сгенерированы функцией сбора, и выполнить там свой SUM(). Чтобы иметь возможность СУММИРОВАТЬ элементы, вы должны FLATTEN() их в единый список, прежде чем суммировать их.

FOR m IN pkg_spp_RegMem
FILTER m.memberId == "40289"
COLLECT member = m.memberId INTO g

RETURN { "memberId" : member, "amount" :  SUM(
                                              FLATTEN(
                                                       (
                                                         FOR r in g[*].m[*].items
                                                         RETURN r[*].amount
                                                       )
                                                     )
                                             )
       }

Это приводит к:

[
  {
    "memberId": "40289",
    "amount": 1250
  }
]
person thesilentman    schedule 10.06.2014
comment
Большое спасибо за Вашу помощь! Я не знал о функции flatten, но при ее вызове получаю сообщение об ошибке: [1540] использование неизвестной функции 'FLATTEN ()'. Это определяется пользователем? В любом случае я с благодарностью принимаю ваш ответ, так как мне удалось изменить предоставленный вами запрос следующим образом, чтобы получить желаемый результат: FOR m IN pkg_spp_RegMem FILTER m.memberId == 40289 COLLECT member = m.memberId INTO g ВОЗВРАТ {memberId: member, amount: SUM ((FOR r IN g [] .m [] .items FOR i IN r RETURN i.amount))} - person Martin; 10.06.2014
comment
FLATTEN () определенно является стандартной функцией массива. Начиная с версии 2.7, вы также сможете выполнять выравнивание с помощью нового оператора с несколькими звездами: arangodb.com/2015/06/aql-improvements-for-2-7 - person CodeManX; 02.08.2015