¿Hay un lenguaje de consulta para JSON?


227

¿Existe un lenguaje similar a SQL o XQuery para consultar JSON?

Estoy pensando en conjuntos de datos muy pequeños que se correlacionan muy bien con JSON, donde sería bueno responder fácilmente consultas como "¿cuáles son todos los valores de X donde Y> 3" o hacer las operaciones habituales de tipo SUM / COUNT?

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 del lado del cliente como del lado del servidor con los resultados que se convierten a la estructura de datos específica del idioma apropiado (o tal vez se mantienen como JSON)

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

¿Alguna sugerencia?

Editar: Esto 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 simplemente hacer las funciones de suma / etc. directamente según sea necesario es que espero construir las consultas se basan dinámicamente en la entrada del usuario. Algo así como el argumento de que "no necesitamos SQL, simplemente podemos escribir las funciones que necesitamos". Eventualmente, eso se sale de control o terminas escribiendo tu propia versión de SQL a medida que lo empujas más y más. (Está bien, sé que es un argumento un poco tonto, pero entiendes la idea ...)


Yo también tengo esa necesidad. Necesito hacer coincidir las solicitudes JSON entrantes por valores específicos en ubicaciones específicas en el árbol de objetos. La consulta tiene que ser configurada por un usuario (avanzado). La solución actual es construir un XML improvisado a partir de JSON y aplicar XPath.
Vladimir Dyuzhev

1
Es más una herramienta de shell, pero jq ( stedolan.github.io/jq ) ha sido increíble para explorar los datos de json. Pruébelo en el patio de recreo: jqplay.org
jtmoulia

Existe una herramienta basada en la web que le permite ejecutar consultas SQL en feeds JSON públicos o API en sqall.co .
Stack Man


Respuestas:


91

Claro, ¿qué tal:

Todos parecen ser un poco trabajo 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árquico vs objeto / estructura).

EDITAR septiembre de 2015: en realidad, ahora hay un estándar de puntero JSON que permite un recorrido muy simple y eficiente del contenido JSON. No solo se especifica formalmente, sino que también es compatible con muchas bibliotecas JSON. Por lo tanto, lo llamaría un estándar útil real real, aunque debido a su expresividad limitada, puede considerarse o no lenguaje de consulta per se.


77
en otras palabras, nada estándar y estable ... :-(
Vladimir Dyuzhev

Hablando de estándar, escuché un rumor de que XQuery 3.1 podría extenderse para admitir consultas JSON (similar a JSONiq ). Por supuesto, podría llevar algún tiempo ya que XQuery 3.0 aún no se ha lanzado oficialmente.
Julien Ribon

Oh misericordia, definitivamente espero que no. Todos los intentos de XML-> JSON que he visto han sido un desastre horrible: los modelos de información son incompatibles. Pero me gustaría ver a JQuery usando las mismas ideas, partes de sintaxis; simplemente modificado correctamente al modelo de información JSON.
StaxMan

1
Para cualquiera que busque una implementación de JSONPath en Ruby: github.com/joshbuddy/jsonpath
Robert Ross

@ GôTô: Usar MongoDB, si tienes esa libertad, parece un enfoque viable. (vea la respuesta a continuación para ver un ejemplo de cómo traducir la consulta al shell incorporado)
serv-inc

48

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 probarla en línea.


@hugoware: ¿hay alguna documentación para esto? ¿Hay alguna consulta que no sea .starts () (como contiene?)
Rikki

55
Última actualización hace 8 años y sin respuesta a la pregunta de si el proyecto está muerto hace 5 años ... Creo que el proyecto está muerto.
cfc


14

jmespath funciona realmente bastante bien y bien, http://jmespath.org/ Está siendo utilizado por Amazon en la interfaz de línea de comandos de AWS, por lo que debe ser bastante estable.


55
Sin embargo, al mismo tiempo en la misma página: "Si necesita funciones más avanzadas que pueden no ser posibles con --query, puede consultar jq, un procesador JSON de línea de comandos". Por lo tanto, parece que AWS usa jmespathel --queryparámetro, pero lo recomienda jqpara la tubería de la línea de comandos. docs.aws.amazon.com/cli/latest/userguide/…
wisbucky

10

JQ es un J SON q lenguaje uery, destinados principalmente a la línea de comandos, pero con los enlaces a una amplia gama de lenguajes de programación (Java, Node.js, PHP, ...) e incluso disponibles en el navegador a través de JQ en la web .

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

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

SUMA (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)

la sintaxis jq extiende la sintaxis JSON

Cada expresión JSON es una expresión jq válida, y expresiones como [1, (1+1)]y {"a": (1 + 1)} `ilustran cómo jq extiende la sintaxis JSON.

Un ejemplo más útil es la expresión jq:

{a,b}

que, dado el valor JSON {"a":1, "b":2, "c": 3}, se evalúa como {"a":1, "b":2}.


8

El array.filter()método incorporado hace que la mayoría de estas llamadas bibliotecas de consulta de JavaScript sean obsoletas

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


55
array.filter()es parte de JavaScript, no JSON.
Iain Samuel McLean Élder

2
JSON es un subconjunto de JavaScript, pero hay muchos lenguajes que admiten JSON y matrices y que tienen un método de filtro de matriz implementado, por lo que este es un punto válido.
dakab


7

ObjectPath es un lenguaje de consulta simple y de peso 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 integradas.

Ejemplo

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

Probablemente en el futuro cercano proporcionaremos 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.


1
Excepto que casi no tiene documentación, por lo que es difícil saber cómo hacer algo como encontrar elementos con texto como algo.
James O'Brien el

1
@ JamesO'Brien Gracias por su comentario: si considera que la referencia es inútil y tiene algún problema específico en mente, infórmenos aquí : alguien intentará ayudarlo. Actualmente estamos trabajando para hacer que los documentos sean más utilizables, me encantan sus comentarios.
Ela Bednarek

Gracias lo aprecio. Me gustaría usar Actualmente estoy usando ashphy.com/JSONPathOnlineEvaluator ?
James O'Brien

No se pudo descubrir cómo usar esto con Javascript debido a una falta total de documentación.
user3670743

Estamos buscando colaboradores para ayudar con eso. Puede escribir en Github o grupos de google groups.google.com/forum/#!members/objectpath lo que está tratando de lograr, y estoy seguro de que alguien responderá sus preguntas.
Ela Bednarek


4

OK, esta publicación es un poco antigua, pero ... si desea hacer una consulta similar a SQL en JSON nativo (u objetos JS) en objetos JS, eche un vistazo a https://github.com/deitch/searchjs

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

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

La implementación de referencia searchjs funciona en el navegador así como en un paquete de nodo npm

npm install searchjs

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

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


3

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

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

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

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


3

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 primeros tres comandos insertan los datos en su colección. (Simplemente inicie el mongodservidor y conéctese con el mongocliente).

Los dos siguientes procesan los datos. $matchfiltros, $groupaplica el sumy list, respectivamente.


2

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


2


Acabo de terminar una versión liberable de un JS-lib del cliente (defiant.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 (no hay nuevas expresiones de sintaxis como en JSONPath).

Ejemplo de cómo funciona (véalo 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 alcance de este tema. De todos modos, puede probar la biblioteca con un evaluador XPath del lado del cliente. Creo que las personas no 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 les sea útil ... Saludos


¿Actualmente es posible obtener la ruta completa a los resultados?
XeniaSis

2
  1. Google tiene un proyecto llamado lovefield ; Me acabo de enterar y parece interesante, aunque es más complicado que simplemente poner 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, usando IndexedDB para almacenar datos localmente. Proporciona una sintaxis similar a SQL y funciona en varios navegadores (actualmente 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/

    Revisando brevemente los ejemplos , parece prometedor, y el documento 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, ligera y extensible que no tiene dependencias. jinqJs proporciona una manera simple de realizar consultas SQL como 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 sintaxis similar a SQL y funcionalidad de predicado. El propósito de jinqJs es proporcionar una experiencia similar a SQL a los programadores familiarizados con las consultas LINQ.


1

Secundaré la noción de solo usar su propio javascript, pero para algo un poco más sofisticado, puede mirar los datos del dojo . No lo he usado, pero parece que le brinda aproximadamente el tipo de interfaz de consulta que está buscando.


1

La implementación actual de Jaql apunta a un gran procesamiento de datos utilizando un clúster Hadoop, por lo que podría ser más de lo que necesita. Sin embargo, se ejecuta fácilmente sin un clúster de Hadoop (pero aún requiere que se compile el código de Hadoop y sus dependencias, que se incluyen principalmente). Una pequeña implementación de Jaql que podría integrarse 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/


1

También puede usar Underscore.js, que es básicamente una biblioteca suiza para manipular colecciones. El uso de _.filter, _.pluck, _.reduceque puede hacer consultas similar a 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 del lado del cliente como del lado del servidor y es una biblioteca notable.

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


1

Siempre que sea posible, cambiaría todas las consultas al backend 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 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 del backend a un navegador, como la mayoría de los casos de uso de JSON. Consulte y filtre en el backend para obtener los datos tan pequeños que se necesitan.

Si por alguna razón necesita consultar en el front-end (principalmente en un navegador), sugeriría simplemente usar array.filter (¿por qué inventar algo más?).

Dicho esto, 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 tenga los datos, es posible que desee mostrarlos de varias maneras. Sin embargo, una vez más, puede hacer mucho de esto en el servidor (que puede ser mucho más fácil de escalar) que en el cliente, SI está utilizando el modelo de cliente servidor <-->.

¡Solo mi valor de 2 peniques!


1

Echa un vistazo a https://github.com/niclasko/Cypher.js (nota: soy el autor)

Es una implementación de Javascript de dependencia cero del lenguaje de consulta de la base de datos de gráficos Cypher junto con una base de datos de gráficos. Se ejecuta en el navegador (probado con Firefox, Chrome, IE).

Con relevancia para la pregunta. Se puede utilizar para consultar puntos finales JSON:

load json from "http://url/endpoint" as l return l limit 10

Aquí hay un ejemplo de consulta de un documento JSON complejo y análisis en él:

Ejemplo de consulta JSON de Cypher.js


1

PythonQL ofrece una sintaxis incorporado que en mi humilde opinión es una mejora en SQL, sobre todo porque group, window, where, let, etc se pueden mezclar libremente.

$ cat x.py
#coding: pythonql
data = [{"x": 2, "y": 0}, {"x": 3, "y": 1}, {"x": 4, "y": 1}]
q = [x match {'x': as x, 'y': as y} in data where y > 0]
print(sum(q))
print(list(q))

q = [x match {'x': as x, 'y': as y} as d in data where d['y'] > 0]
print(sum(q))

Este código muestra dos respuestas diferentes a su pregunta, dependiendo de su necesidad de manejar toda la estructura o solo el valor. La ejecución te da el resultado esperado.

$ python x.py
7
[3, 4]
7

0

Podrías usar linq.js.

Esto permite utilizar agregaciones y selecciones de un conjunto de datos de objetos, como datos de otras estructuras.

var data = [{ x: 2, y: 0 }, { x: 3, y: 1 }, { x: 4, y: 1 }];

// SUM(X) WHERE Y > 0     -> 7
console.log(Enumerable.From(data).Where("$.y > 0").Sum("$.x"));

// LIST(X) WHERE Y > 0    -> [3, 4]
console.log(Enumerable.From(data).Where("$.y > 0").Select("$.x").ToArray());
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.