2015-05-11 4 views
1

Я хотел бы сортировать по полю в определенном порядке, скажем, 2,4,1,5,3.ArangoDB custom sort order

В MySQL я мог бы использовать ORDER BY FIELD(id,2,4,1,5,3).

Есть ли что-то эквивалентное для ArangoDB?

ответ

7

Я думаю, что это должно быть возможно использовать функцию POSITION AQL, который может вернуть позицию элемента внутри массива

FOR i IN [ 1, 2, 3, 4, 5 ]     /* what to iterate over */ 
    SORT POSITION([ 2, 4, 1, 5, 3 ], i, true) /* order to be returned */ 
    RETURN i 

Это вернет:

[ 2, 4, 1, 5, 3 ] 

Обновление: в мой первоначальный ответ включен CONTAINS AQL функция, однако, это должно быть POSITION!

+0

Конечно, да, ПОЗИЦИЯ() с ней легче работать. Однако, я думаю, что это не является прямым эквивалентом функциональности OP, поскольку он возвращает только определенные значения в определенном порядке. Он не возвращает остальные значения набора результатов после этого, как предполагает функциональность MYSQL. Однако это было бы неплохо заменить первую часть моего предложения. :) – thesilentman

+0

тестирования с: ПОЗИЦИИ ([1,5,3], Я, истинные) возвращает [ 2, 4, 1, 5, ] , который не был бы желаемый результат, за исключением случаев, когда заданный порядок сортировки задается для каждого возможного значения в наборе результатов. – thesilentman

+0

Не возвращает ли MySQL 'FIELD' 0, если элемент отсутствует в списке значений сравнения? «POSITION» AQL аналогичен: он вернет -1, если значение не содержится в массиве поиска. MySQL вернет позиции, начинающиеся с 1, и AQL вернет позиции, начинающиеся с 0, но это не должно влиять на порядок результатов. В MySQL и AQL внутренний порядок элементов, которые не содержатся в списке поиска/массиве, не определен, но если это важно, для их сортировки можно добавить дополнительное условие поиска, например. 'SORT POSITION ([2, 4, 1, 5, 3], i, true), i ASC'. – stj

1

К сожалению, на данный момент нет прямого эквивалента.

Однако есть способы сделать это самостоятельно.

1) Построив запрос AQL: Запрос будет проходить через ваш массив значений сортировки и запросить БД для каждого определенного значения. Затем каждый из этих результатов будет добавлен в конечный выходной массив.

Помните, что у этого есть оценка производительности, потому что для каждого значения есть один запрос. Если вы определяете только несколько из них, я думаю, что это будет терпимо, но если вам нужно определить, например, десятки или сотни, это приведет к n + 1 запросам (где n - количество настраиваемых сортированных значений).

«+1» - это последний запрос, который должен получить результат всех других значений, которые не определены в вашем настраиваемом массиве сортировки, а также добавить их в ваш выходной массив.

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

Примечания для сниппета:

  • Я первый для создания массива, который будет представлять коллекцию мы бы запрос.
  • Затем я устанавливаю определенные значения сортировки.
  • После этого фактическая инструкция AQL выполняет свою работу.
  • Также обратите внимание на функцию FLATTEN во внешнем операторе RETURN, что требуется, поскольку в первом цикле мы получаем массивы результатов для каждого определенного значения сортировки. Все они должны быть сглажены до одного уровня, чтобы обрабатываться как уникальный набор результатов (а не многие инкапсулированные маленькие).

/* Define a dummy collection-array to work with */ 
 
LET a = [ 
 
    { 
 
"_id": "a/384072353674", 
 
"_key": "384072353674", 
 
"_rev": "384073795466", 
 
"sort": 2 
 
    }, 
 
    { 
 
"_id": "a/384075040650", 
 
"_key": "384075040650", 
 
"_rev": "384075827082", 
 
"sort": 3 
 
    }, 
 
    { 
 
"_id": "a/384077137802", 
 
"_key": "384077137802", 
 
"_rev": "384078579594", 
 
"sort": 4 
 
    }, 
 
    { 
 
"_id": "a/384067504010", 
 
"_key": "384067504010", 
 
"_rev": "384069732234", 
 
"sort": 1 
 
    }, 
 
    { 
 
"_id": "a/384079497098", 
 
"_key": "384079497098", 
 
"_rev": "384081004426", 
 
"sort": 5 
 
    } 
 
] 
 

 
/* Define the custom sort values */ 
 
LET cSort = [5,3,1] 
 

 
/* Gather the results of each defined sort value query into definedSortResults */ 
 
LET definedSortResults = (
 
FOR u in cSort 
 
    LET d = (
 
    FOR docs IN `a` 
 
     FILTER docs.`sort` == u 
 
     RETURN docs 
 
    ) 
 
    RETURN d 
 
) 
 

 
/* Append the the result of the last (all the non-defined sort values) query to the results of the definedSortResults into the output array */ 
 
LET output = (
 
APPEND (definedSortResults, (
 
    FOR docs IN `a` 
 
      FILTER docs.`sort` NOT IN cSort 
 
      RETURN docs 
 
    ) 
 
) 
 
) 
 

 
/* Finally FLATTEN and RETURN the output variable */ 
 
RETURN FLATTEN(output)

2) Другой подход был бы, чтобы расширить AQL с функцией, написанной в JavaScript, что бы сделать по существу те же самые шаги, как описано выше.

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

Надежда, что помогает