Requête de type sql sur un objet javascrip complexe

Soyez le premier à donner votre avis sur cette source.

Vue 4 361 fois - Téléchargée 233 fois

Description

Bonjour,

Cette fois-ci je poste un script qui permet, à partir de n'importe quel tableau d'objets complexes et hétérogènes, d'effectuer une sélection d'objets en utilisant une syntaxe proche du SQL.
Le script est hébergé à l'adresse :
http://svn.openihs.org/jsprojects/trunk/toolkit/js/array.js
si vous avez un 404 not found, vérifiez qu'il n'y a pas d'espaces dans l'URL !

Ce script ajoute une méthode query à tous les tableau (plus exactement au prototype Array).

Fonction :
Array.prototype.query(request[, arg1..N])

Arguments :
request de type String et dont le format est REQUEST (voir ci-dessous)
arg1..N de tout type qui sont les éléments référencés dans la requête

Grammaire (la flemme de traduire) :
  • REQUEST := select FIELD_LIST [where CLAUSE_LIST] [limit [OFFSET,]LIMIT]
  • FIELD_LIST := * | FIELD[, FIELD[, FIELD[, etc.]]]
  • FIELD := PATH [as ALIAS]
  • PATH := object path foo.bar (must match with /[\w\.]+/)
  • ALIAS := result field name (must match with /\w+/)
  • CLAUSE_LIST := CLAUSE [EXP_OP CLAUSE [EXP_OP CLAUSE [etc]]]
  • parenthesis are allowed eg (CLAUSE EXP_OP CLAUSE) EXP_OP CLAUSE, etc.
  • EXP_OP := and | or
  • CLAUSE := PATH OP VALUE
  • OP := =(equals)|<>(not equals)|!=(not equals)|~(match)|!~(don't match)
  • VALUE := true|false|null|NUMBER|STRING|TAG
  • NUMBER := a number (must match with /\d+/)
  • STRING := a string (must match with /("[\"]+")|('[\']+')/)
  • WARNING: escaped quotes or double quotes is not supported: use TAG instead
  • TAG := %1..n refer to arg1..N
  • OFFSET := offset index
  • LIMIT := number of returned occurrences beginning at OFFSET index.


NOTES :
1. C'est une fonctionnalité que j'ai codé assez rapidement, en grande partie le matin dans le TGV en allant au boulot, donc soyez indulgent :-)
2. Bien entendu mon script n'a pas vocation de faire un SGBD en javascript
3. Les seuls opérateurs logiques supportés (entre les expressions) sont le "and" et le "or" (pas de "not")

Exemples d'utilisation.
On part du tableau suivant :

Source / Exemple :


addressBook = [
  {
    name: "Paul Durant",
    phone: [
      {type: "work", number: "0123456789"},
      {type: "cellular", prefered: true, number: "0654321987"}
    ],
    addresses: [
      {type: "work", street: "123 rue Truck", postal_code: "92000", city: "Nanterre"}
    ]
  }, {
    name: "Jean Dupont",
    phone: [
      {type: "home", prefered: true, number: "0987654321"},
      { type: "cellular", number: "0789456123"}
    ],
    addresses: [
      {type: "home",  street: "403 rue Inconnue", postal_code: "99999", city: "Laville"}
    ]
  }, {
    name: "Nicolas Duchmole",
    phone: [
      {type: "home", prefered: true, number: "0258147369"},
      {type: "cellular", number: "0639528417"}
    ]
  }, {
    name: "Jean Durant",
    phone: [
      {type: "home", number: "0545654582"},
      {type: "cellular", prefered: true, number: "0654123987"}
    ],
    addresses: [
      {type: "home", street: "le coin paumé", postal_code: "11111", city: "La ville perdue"}
    ]
  }
];

Conclusion :


Maintenant, quelques exemples de requêtes...
dans les cas suivants je sélectionne des champs précis mais il y a la possibilité de récupérer les objets dans leur ensemble en mettant "select * [...]"

addressBook.query("select name, addresses.city where addresses.type = \"home\"") donne :
[{"name":"Jean Dupont","city":"Laville"},{"name":"Jean Durant","city":"La ville perdue"}]

addressBook.query("select name, phone.number as phoneNumber where (addresses.type = \"home\" or phone.type = \"work\") and name ~ %1", /Durant$/) donne :
[{"name":"Paul Durant","phoneNumber":"0123456789"},{"name":"Jean Durant","phoneNumber":"0545654582"}]

addressBook.query("select name, phone.number as phoneNumber where phone.prefered = true limit 1,2") donne :
[{"name":"Jean Dupont","phoneNumber":"0987654321"},{"name":"Nicolas Duchmole","phoneNumber":"0258147369"}]

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
11
Date d'inscription
vendredi 28 septembre 2007
Statut
Membre
Dernière intervention
14 avril 2011

@emericv
Parfait, merci
Messages postés
16
Date d'inscription
samedi 5 février 2005
Statut
Membre
Dernière intervention
24 novembre 2009

@Djtadpole
en fait le moteur de rendu du site rajoute un espace dans mon URL ce qui la rend invalide
j'ai rajouté un ZIP contenant le fichier en question
Messages postés
11
Date d'inscription
vendredi 28 septembre 2007
Statut
Membre
Dernière intervention
14 avril 2011

Bonjour,
cela a l'air pas mal.
Cependant, c'est moi ou on ne peut pas télécharger le code ?
merci.
Messages postés
16
Date d'inscription
samedi 5 février 2005
Statut
Membre
Dernière intervention
24 novembre 2009

@Kimjoa

> Sinon j'ai fait une source ce rapprochant un peux de la tienne tu devrait y jeter un oeil... a++
en effet j'ai vu ça juste après avoir posté le mien, et c'est vrai que c'est assez similaire.
(vu dans la section "Sources en rapport avec celle ci")
Messages postés
16
Date d'inscription
samedi 5 février 2005
Statut
Membre
Dernière intervention
24 novembre 2009

@Kimjoa

> tu devrais encapsuler tes variables et méthodes privée, dans une fonction anonyme
je pensais le faire justement, voilà qui est fait!
> Ça serait cool de pouvoir mettre dans la clause where des select, un système de jointure
Bin au fait je ne sais pas si tu a remarqué, mais il y a déjà un système de jointure automatique:si tu fais un select sur un numéro de tel par exemple et que dans la clause where tu met phone.type "cellular" il te retournera les numéros de portable. Autrement (en l’absence de clause phone._arrt_ "qqch" par ex...), il retourne le premier numéro de la liste. La où mon système a ses limites c'est qu'il n'est pas capable de faire des vrais jointures et te retourner des résultats du genre
Nom1 tel1
Nom1 tel2
Nom2 tel1
Nom2 tel2
etc.
Cependant il reste toujours la possibilité de récupérer l'objet dans son ensemble...
Afficher les 6 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.