简体   繁体   中英

ArangoDB custom sort order

I would like to sort by a field in a specific order, lets say 2,4,1,5,3.

In MySQL I could use ORDER BY FIELD(id,2,4,1,5,3) .

Is there anything equivalent for ArangoDB?

I think it should be possible to use the POSITION AQL function, which can return the position of an element inside an array

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

This will return:

[ 2, 4, 1, 5, 3 ]

Update : my original answer included the CONTAINS AQL function, however, it should be POSITION !

Unfortunately, there is no direct equivalent for that, at the moment.

However, there are ways to accomplish that by yourself.

1) By constructing an AQL query: The query would run through your sort value array and query the DB for every defined value. Each of those results would then be added to the final output array.

Mind you, that this does have a performance penalty, because there is one query for every value. If you are defining only a few ones, I guess it will be tolerable, but if you have to define for example tens or hundreds, it will lead to n+1 queries (where n is the number of custom sorted values).

The "+1" is the last query, which should get the result of all the other values, which are not defined in your custom sort array and also append these to your output array.

That would look like the following snippet, which you can copy into your AQL Editor and run it.

Notes for the snippet:

  • I am first creating an array, which would represent the collection we would query.
  • Then I am setting the defined sort values.
  • After that, the actual AQL statement does its job.
  • Also, note the FLATTEN function at the outer RETURN statement, which is required, because in the first loop we are getting result arrays for each defined sort value. These have all to be flatten down to the same level in order to be processed as a unique result set (instead of many encapsulated small ones).

 /* 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) A different approach would be, to extend AQL with a function written in JavaScript, that would essentially do the same steps as above.

Of course, you could also open up a feature request on ArangoDB's GitHub Page, and maybe the nice folks at ArangoDB will consider it for inclusion. :)

Hope that helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM