¿Hay un lenguaje de consulta para JSON?

¿Hay un lenguaje (más o menos) SQL o XQuery para consultar JSON?

Estoy pensando en conjuntos de datos muy pequeños que se relacionan muy bien con JSON, donde sería bueno responder fácilmente a consultas como “¿Cuáles son todos los valores de X donde Y> 3” o hacer las operaciones de tipo SUMARIO / RECUENTO habitual?

Como ejemplo completamente inventado, algo como esto:

[{"x": 2, "y": 0}}, {"x": 3, "y": 1}, {"x": 4, "y": 1}] SUM(X) WHERE Y > 0 (would equate to 7) LIST(X) WHERE Y > 0 (would equate to [3,4]) 

Estoy pensando que esto funcionaría tanto en el lado del cliente como en el lado del servidor y los resultados se convertirán a la estructura de datos específica del idioma adecuada (o tal vez se mantendrá como JSON)

Una búsqueda rápida en Google sugiere que la gente ha pensado en ello y ha implementado algunas cosas ( JAQL ), pero no parece que haya surgido un uso estándar o un conjunto de bibliotecas. Si bien cada función es bastante trivial de implementar por sí misma, si alguien ya lo hizo bien, no quiero volver a inventar la rueda.

¿Alguna sugerencia?

Editar: Esto realmente puede ser una mala idea o JSON puede ser un formato demasiado genérico para lo que estoy pensando. La razón para querer un lenguaje de consulta en lugar de solo hacer las funciones de sum / etc directamente según sea necesario es que espero construir las consultas dinámicamente basadas en la entrada del usuario. Me gusta el argumento de que “no necesitamos SQL, podemos simplemente escribir las funciones que necesitamos”. Eventualmente, o se sale de control o termina escribiendo su propia versión de SQL a medida que la empuja más y más. (De acuerdo, sé que es un argumento un poco tonto, pero entiendes la idea …)

Claro, ¿qué tal?

  • JaQL
  • JsonPath .
  • Json Query

Todos parecen estar un poco en progreso, pero funcionan hasta cierto punto. También son similares a XPath y XQuery conceptualmente; a pesar de que XML y JSON tienen diferentes modelos conceptuales (jerárquica vs objeto / estructura).

EDITAR Sep-2015: en realidad ahora existe el estándar JSON Pointer que permite un cruce muy simple y eficiente del contenido JSON. No solo se especifica formalmente, sino que también es compatible con muchas bibliotecas JSON. Así que lo llamaría estándar realmente útil real, aunque debido a su limitada expresividad puede o no considerarse Lenguaje de Consulta per se.

Yo recomendaría mi proyecto en el que estoy trabajando llamado jLinq . Estoy buscando comentarios, así que estaría interesado en escuchar lo que piensas.

Si le permite escribir consultas similares a como lo haría en LINQ …

 var results = jLinq.from(records.users) //you can join records .join(records.locations, "location", "locationId", "id") //write queries on the data .startsWith("firstname", "j") .or("k") //automatically remembers field and command names //even query joined items .equals("location.state", "TX") //and even do custom selections .select(function(rec) { return { fullname : rec.firstname + " " + rec.lastname, city : rec.location.city, ageInTenYears : (rec.age + 10) }; }); 

¡Es completamente extensible también!

La documentación aún está en progreso, pero aún puede intentarlo en línea.

Actualización: XQuery 3.1 puede consultar XML o JSON, o ambos juntos. Y XPath 3.1 también puede.

La lista está creciendo:

  • JSONiq (basado en XQuery)
  • UNQL (como SQL)
  • JaQL (funcional)
  • JsonPath ( similar a XPath)
  • Json Query (tipo de XPath)
  • GraphQL (basado en plantilla, typescript)

El método incorporado array.filter() hace obsoletas a la mayoría de estas llamadas bibliotecas de consultas javascript.

Puede poner tantas condiciones dentro del delegado como pueda imaginar: comparación simple, startsWith, etc. No lo he probado, pero probablemente también podría anidar filtros para consultar las colecciones internas.

jmespath funciona bastante bien y muy bien, http://jmespath.org/ Lo usa Amazon en la interfaz de línea de comandos de AWS, por lo que tiene que ser bastante estable.

Si está usando .NET entonces Json.NET soporta consultas LINQ sobre la parte superior de JSON. Esta publicación tiene algunos ejemplos. Es compatible con filtrado, mapeo, agrupamiento, etc.

Otra forma de ver esto sería usar mongoDB . Puede almacenar su JSON en mongo y luego consultarlo a través de la syntax de la consulta de mongodb.

ObjectPath es un lenguaje de consulta simple y ligero para documentos JSON de estructura compleja o desconocida. Es similar a XPath o JSONPath, pero mucho más potente gracias a los cálculos aritméticos integrados, los mecanismos de comparación y las funciones incorporadas.

Ejemplo

La versión de Python es madura y se usa en producción. JS todavía está en beta.

Probablemente en un futuro próximo proporcionemos una versión completa de Javascript. También queremos desarrollarlo aún más, para que pueda servir como una alternativa más simple a las consultas de Mongo.

OK, esta publicación es un poco antigua, pero … si quieres hacer una consulta similar a SQL en JSON nativos (o objetos JS) en objetos JS, echa un vistazo a https://github.com/deitch/searchjs

Es un lenguaje jsql escrito completamente en JSON, y una implementación de referencia. Puedes decir: “Quiero encontrar todos los objetos en una matriz que tengan el nombre ===” John “&& age === 25 como:

 {name:"John",age:25,_join:"AND"} 

La búsqueda de implementación de referencia funciona tanto en el navegador como en un paquete node npm

 npm install searchjs 

También puede hacer cosas como combinaciones complejas y negación (NO). Nativamente ignora el caso.

Todavía no sum ni cuenta, pero probablemente sea más fácil hacerlo fuera.

Aquí hay algunas bibliotecas de JavaScript simples que también harán el truco:

  • Dollar Q es una buena biblioteca liviana. Tiene una sensación familiar a la syntax de encadenamiento popularizada por jQuery y solo tiene 373 SLOC.
  • SpahQL es un lenguaje de consulta con todas las funciones con una syntax similar a XPath ( Homepage , Github
  • jFunk es un lenguaje de consulta en progreso, con una syntax similar a los selectores de CSS / jQuery. Parecía prometedor, pero no ha tenido ningún desarrollo más allá de su compromiso inicial.

  • (agregado en 2014): la herramienta de línea de comandos jq tiene una syntax ordenada, pero desafortunadamente es una biblioteca de CA. Ejemplo de uso:

    < package.json jq '.dependencies | to_entries | .[] | select(.value | startswith("git")) | .key'

En MongoDB , así es como funcionaría (en el shell mongo, existen controladores para un idioma de su elección).

 db.collection.insert({"x": 2, "y": 0}); // notice the ':' instead of ',' db.collection.insert({"x": 3, "y": 1}); db.collection.insert({"x": 4, "y": 1}); db.collection.aggregate([{$match: {"y": {$gt: 0}}}, {$group: {_id: "sum", sum: {$sum: "$x"}}}]); db.collection.aggregate([{$match: {"y": {$gt: 0}}}, {$group: {_id: "list", list: {$push: "$x"}}}]); 

Los tres primeros comandos insertan los datos en su colección. (Simplemente inicie el servidor mongod y conéctese con el cliente mongo ).

Los siguientes dos procesan los datos. $match filtros, $group aplica la sum y la list , respectivamente.

jq es un lenguaje de J SON q uery, destinado principalmente para la línea de comandos pero con enlaces a una amplia gama de lenguajes de progtwigción (Java, node.js, php, …) e incluso disponible en el navegador a través de jq-web .

Aquí hay algunas ilustraciones basadas en la pregunta original, que dieron este JSON como ejemplo:

  [{"x": 2, "y": 0}}, {"x": 3, "y": 1}, {"x": 4, "y": 1}] 

SUM (X) DONDE Y> 0 (equivaldría a 7)

 map(select(.y > 0)) | add 

LISTA (X) DONDE Y> 0 (equivaldría a [3,4])

 map(.y > 0) 

SpahQL es el más prometedor y mejor pensado de estos, por lo que puedo decir. Recomiendo echarle un vistazo.

Acabo de terminar una versión liberable de un cliente JS-lib (desafiant.js) que hace lo que estás buscando. Con defiant.js, puede consultar una estructura JSON con las expresiones XPath con las que está familiarizado (sin nuevas expresiones de syntax como en JSONPath).

Ejemplo de cómo funciona (ver en el navegador aquí http://defiantjs.com/defiant.js/demo/sum.avg.htm ):

 var data = [ { "x": 2, "y": 0 }, { "x": 3, "y": 1 }, { "x": 4, "y": 1 }, { "x": 2, "y": 1 } ], res = JSON.search( data, '//*[ y > 0 ]' ); console.log( res.sum('x') ); // 9 console.log( res.avg('x') ); // 3 console.log( res.min('x') ); // 2 console.log( res.max('x') ); // 4 

Como puede ver, DefiantJS extiende el objeto global JSON con una función de búsqueda y la matriz devuelta se entrega con funciones agregadas. DefiantJS contiene algunas otras funcionalidades, pero están fuera del scope de este tema. Anywho, puedes probar la lib con un XPath Evaluator del lado del cliente. Creo que las personas que no están familiarizadas con XPath encontrarán útil este evaluador.
http://defiantjs.com/#xpath_evaluator

Más información sobre defiant.js
http://defiantjs.com/
https://github.com/hbi99/defiant.js

Espero que lo encuentres útil … Saludos

  1. Google tiene un proyecto llamado lovefield ; acabo de enterarme, y se ve interesante, aunque es más complicado que simplemente colocar guiones bajos o lodash.

    https://github.com/google/lovefield

Lovefield es un motor de consulta relacional escrito en JavaScript puro. También proporciona ayuda con datos persistentes en el lado del navegador, por ejemplo, utilizando IndexedDB para almacenar datos localmente. Proporciona syntax similar a SQL y funciona en todos los navegadores (actualmente es compatible con Chrome 37+, Firefox 31+, IE 10+ y Safari 5.1 + …


  1. Otra entrada reciente interesante en este espacio llamada jinqJs .

    http://www.jinqjs.com/

    Al revisar brevemente los ejemplos , se ve prometedor, y el documento de la API parece estar bien escrito.


 function isChild(row) { return (row.Age < 18 ? 'Yes' : 'No'); } var people = [ {Name: 'Jane', Age: 20, Location: 'Smithtown'}, {Name: 'Ken', Age: 57, Location: 'Islip'}, {Name: 'Tom', Age: 10, Location: 'Islip'} ]; var result = new jinqJs() .from(people) .orderBy('Age') .select([{field: 'Name'}, {field: 'Age', text: 'Your Age'}, {text: 'Is Child', value: isChild}]); 

jinqJs es una biblioteca javaScript pequeña, simple, liviana y extensible que no tiene dependencias. jinqJs proporciona una forma simple de realizar consultas tipo SQL en matrices javaScript, colecciones y servicios web que devuelven una respuesta JSON. jinqJs es similar a la expresión Lambda de Microsoft para .Net, y proporciona capacidades similares para consultar colecciones usando una syntax y funcionalidad de predicado similar a SQL. El propósito de jinqJs es proporcionar una experiencia similar a SQL a los progtwigdores familiarizados con las consultas LINQ.

Subrayaré la noción de simplemente usar tu propio javascript, pero para algo un poco más sofisticado podrías mirar los datos del dojo . No lo he usado, pero parece que le da aproximadamente el tipo de interfaz de búsqueda que está buscando.

La implementación actual de Jaql tiene como objective el procesamiento de datos grandes usando un clúster de Hadoop, por lo que podría ser más de lo que necesita. Sin embargo, se ejecuta fácilmente sin un clúster Hadoop (pero aún requiere el código Hadoop y sus dependencias para comstackrse, que en su mayoría están incluidos). Una pequeña implementación de Jaql que podría estar incorporada en Javascript y un navegador sería una gran adición al proyecto.

Sus ejemplos anteriores se escriben fácilmente en jaql:

 $data = [{"x": 2, "y": 0}, {"x": 3, "y": 1}, {"x": 4, "y": 1}]; $data -> filter $.y > 0 -> transform $.x -> sum(); // 7 $data -> filter $.y > 0 -> transform $.x; // [3,4] 

Por supuesto, hay mucho más también. Por ejemplo:

 // Compute multiple aggregates and change nesting structure: $data -> group by $y = $.y into { $y, s:sum($[*].x), n:count($), xs:$[*].x}; // [{ "y": 0, "s": 2, "n": 1, "xs": [2] }, // { "y": 1, "s": 7, "n": 2, "xs": [3,4] }] // Join multiple data sets: $more = [{ "y": 0, "z": 5 }, { "y": 1, "z": 6 }]; join $data, $more where $data.y == $more.y into {$data, $more}; // [{ "data": { "x": 2, "y": 0 }, "more": { "y": 0, "z": 5 }}, // { "data": { "x": 3, "y": 1 }, "more": { "y": 1, "z": 6 }}, // { "data": { "x": 4, "y": 1 }, "more": { "y": 1, "z": 6 }}] 

Jaql se puede descargar / discutir en http://code.google.com/p/jaql/

También puede usar Underscore.js, que es básicamente una biblioteca suiza para manipular colecciones. Usando _.filter , _.pluck , _.reduce puedes hacer consultas tipo SQL.

 var data = [{"x": 2, "y": 0}, {"x": 3, "y": 1}, {"x": 4, "y": 1}]; var posData = _.filter(data, function(elt) { return elt.y > 0; }); // [{"x": 3, "y": 1}, {"x": 4, "y": 1}] var values = _.pluck(posData, "x"); // [3, 4] var sum = _.reduce(values, function(a, b) { return a+b; }); // 7 

Underscore.js funciona tanto en el lado del cliente como en el servidor y es una biblioteca notable.

También puede usar Lo-Dash, que es una bifurcación de Underscore.js con mejores actuaciones.

Siempre que sea posible, cambiaría todas las consultas al servidor en el servidor (a la base de datos SQL u otro tipo de base de datos nativa). La razón es que será más rápido y más optimizado para hacer las consultas.

Sé que jSON puede ser independiente y puede haber +/- por tener un lenguaje de consulta, pero no puedo ver la ventaja si está recuperando datos desde el back-end a un navegador, como la mayoría de los casos de uso de JSON. Consulta y filtra en el back-end para obtener los datos tan pequeños que se necesiten.

Si por algún motivo necesita consultar en el front-end (principalmente en un navegador), le sugiero que use simplemente array.filter (¿por qué inventar algo más?).

Dicho lo que creo que sería más útil es una API de transformación para json … son más útiles ya que una vez que tienes los datos, es posible que quieras mostrarlos de varias maneras. Sin embargo, de nuevo, puede hacer mucho de esto en el servidor (que puede ser mucho más fácil de escalar) que en el cliente – SI está usando el modelo de cliente del servidor <->.

¡Solo vale mi penique de 2!

Intereting Posts