2017-08-11 1 views
2

Je voudrais trier le résultat en fonction de l'entrée de l'utilisateur.ArangoDB - Trier le résultat en aql avec la fonction personnalisée

Disons que je objet sort qui pourrait ressembler à ceci:

var sort = {createdAt: -1} 

ou comme ceci:

var sort = {createdAt: 1, name: 1} 

Et j'ai requête qui ressemble à ceci:

FOR f in [{createdAt: 123, name: 'BBB'},{createdAt: 2000, name: 'ZZZ'}, {createdAt: 2000, name: 'BBB'}] 
    SORT f.createdAt DESC 
    RETURN f 

et ça marche bien. Mais j'aimerais trier le résultat par champ qui est passé dans l'objet de tri par utilisateur. J'ai ajouté la fonction Arango personnalisée:

db.createFunction(
    'CUSTOM::FILTERING::SORT_STRING', 
      String(function (sort, it) { 
        return sort && Object.keys(sort).length !== 0 && sort.constructor === Object ? Object.keys(sort).map(key => `${it}.${key} ${sort[key] >= 0 ? 'ASC' : 'DESC'}`).join(', ') : ''; 
      }) 
     ); 

mais quand je l'utilise de cette façon, il ne fonctionne pas du tout. Le résultat n'est pas trié de quelque façon que ce soit:

FOR f in [{createdAt: 123, name: 'BBB'},{createdAt: 2000, name: 'ZZZ'}, {createdAt: 2000, name: 'BBB'}] 
    SORT CUSTOM::FILTERING::SORT_STRING(${sort}, 'f') 
    RETURN f 

Comment puis-je trier les résultats en fonction de différents arguments d'entrée?

+0

Avez-vous jeté un oeil à Foxx Microservices au sein d'ArangoDB? C'est une application parfaite d'entre eux, laissez Foxx présenter une API REST et ensuite l'utilisateur peut fournir des attributs Sort, PageNum, PageSize, Query et l'API REST de Foxx le fera pour vous. –

+0

@DavidThomas pourriez-vous me donner un exemple de la mettre en œuvre? – MatiK

+0

Jetez un oeil à [cette réponse] (https://stackoverflow.com/questions/42427063/sending-http-post-request-from-node-to-foxx-service-arangodb/42451340#42451340) où j'ai fourni un Exemple de configuration d'un microservice Foxx pour répondre à une demande d'API REST. Vous pouvez autoriser l'appelant à fournir des paramètres de requête supplémentaires via le chemin, la chaîne de requête ou le corps, puis demander à votre code d'appeler les requêtes appropriées. Comment écrire Foxx Microservice est au-delà de la portée de cette question, mais il suit un format de style Node.js et il y a beaucoup d'exemples en ligne, en particulier sur github.com. –

Répondre

1

pur AQL, vous pouvez le faire, mais quelque part dans le monde un chiot mourras ...

RETURN (@sortBy == 'createdAt' ? 
    (FOR d IN @@collectionName 
    SORT createdAt DESC 
    RETURN d) : (@sortBy == 'name' ? 
     (FOR d in @@collectionname 
     SORT name DESC 
     RETURN d) 
    ) 
) 
) 

Mais l'autre est de générer dynamiquement l'AQL, avec le code approprié, vous pouvez vérifier le faire en toute sécurité .

Je génère parfois AQL dynamiquement, mais tous les paramètres sont soigneusement analysés, nettoyés, protégés contre les schémas Joi et validés pour arrêter l'injection SQL.

L'autre façon de faire cette requête de style est:

LET sortByCreatedAt = (
    FOR d in @@collectionName 
    SORT createdAt DESC 
    RETURN d) 

LET sortByName = (
    FOR d in @@collectionName 
    SORT name DESC 
    RETURN d) 

RETURN (@sortBy == 'createdAt') ? sortByCreatedAt : sortByName 

Ce n'est pas jolie, mais fonctionne, et avec créativité, vous pouvez écrire des requêtes très imbriqués et complexes avec l'ASC et DESC en option, ainsi comme un nombre prédéfini de noms de colonnes. Il est important de noter que les noms de colonnes ne peuvent pas être entièrement dynamiques, mais peuvent être sélectionnés par l'utilisateur.

Je ne les ai pas testés sur un serveur ArangoDB donc certaines erreurs peuvent exister.

+0

Je ne peux pas le faire non-dynamiquement. J'ai parfois besoin de trier par nom et le champ createdAt, parfois seulement par createdAt. Il y a trop de permutations pour écrire chaque cas séparément. Je voudrais également le réutiliser avec d'autres requêtes. Je peux écrire une fonction qui crée une telle chaîne dynamiquement, mais je ne peux pas utiliser la balise js aql lors de l'appel de la requête db. Dommage qu'il n'y ait pas de moyen facile de faire le tri avec arango :( – MatiK

+0

Le tri est facile .. y at-il une raison pour laquelle vous ne pouvez pas utiliser Foxx ou générer dynamiquement votre AQL avant de l'envoyer? –

+0

Je ne peux pas utiliser Foxx AQL ne fonctionne pas avec la balise js aql, elle échoue en raison des restrictions de sécurité, je ne veux pas être vunerable aux injections, si je fais moi-même la validation, il y a toujours le risque que je manque – MatiK