Existe uma linguagem de consulta para JSON?


227

Existe uma linguagem semelhante a SQL ou XQuery para consultar JSON?

Estou pensando em conjuntos de dados muito pequenos que são bem mapeados para JSON, onde seria bom responder facilmente a consultas como "quais são todos os valores de X onde Y> 3" ou para executar as operações usuais do tipo SUM / COUNT.

Como exemplo completamente inventado, algo como isto:

[{"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])

Eu estou pensando que isso funcionaria tanto do lado do cliente quanto do servidor, com os resultados sendo convertidos na estrutura de dados específica do idioma apropriada (ou talvez mantida como JSON)

Uma rápida pesquisa no Google sugere que as pessoas pensaram sobre isso e implementaram algumas coisas ( JAQL ), mas não parece que um uso padrão ou conjunto de bibliotecas tenha surgido ainda. Embora cada função seja bastante trivial de implementar por conta própria, se alguém já fez isso corretamente, não quero reinventar a roda.

Alguma sugestão?

Edit: Isso pode realmente ser uma má idéia ou JSON pode ser um formato muito genérico para o que estou pensando. O motivo para querer uma linguagem de consulta em vez de apenas executar as funções de soma / etc diretamente, conforme necessário, é que espero criar as consultas dinamicamente com base na entrada do usuário. Como o argumento de que "não precisamos de SQL, podemos apenas escrever as funções que precisamos". Eventualmente, isso sai do controle ou você acaba escrevendo sua própria versão do SQL à medida que avança cada vez mais. (Ok, eu sei que isso é um argumento meio bobo, mas você entendeu ..)


Eu também tenho essa necessidade. Preciso corresponder solicitações JSON recebidas por valores específicos em locais específicos na árvore de objetos. A consulta realmente deve ser configurada por um usuário (avançado). A solução atual é criar um XML improvisado a partir do JSON e aplicar o XPath.
Vladimir Dyuzhev

1
É mais uma ferramenta de shell, mas o jq ( stedolan.github.io/jq ) tem sido incrível para explorar dados do json. Experimente no playground: jqplay.org
jtmoulia

Existe uma ferramenta baseada na Web que permite executar consultas SQL em feeds JSON públicos ou APIs em sqall.co .
Homem Stack


Respostas:


91

Claro, que tal:

Todos eles parecem ter um pouco de trabalho em andamento, mas funcionam até certo ponto. Eles também são semelhantes ao XPath e XQuery conceitualmente; mesmo que XML e JSON tenham modelos conceituais diferentes (hierárquico x objeto / estrutura).

EDIT Set-2015: Atualmente, agora existe o padrão JSON Pointer que permite uma passagem muito simples e eficiente do conteúdo JSON. Ele não é apenas formalmente especificado, mas também é suportado por muitas bibliotecas JSON. Então, eu chamaria isso de padrão útil real real, embora, devido à sua expressividade limitada, possa ou não ser considerado o Query Language por si só.


77
em outras palavras, nada padrão e estável ... :-(
Vladimir Dyuzhev 24/04

Falando sobre padrão, ouvi rumores de que o XQuery 3.1 poderia ser estendido para suportar consultas JSON (semelhante ao JSONiq ). Obviamente, pode levar algum tempo, pois o XQuery 3.0 ainda não foi lançado oficialmente.
Julian Ribon

Oh misericórdia, eu definitivamente espero que não. Todas as tentativas de XML-> JSON que eu vi foram uma bagunça horrível - os modelos de informação são incompatíveis. Mas eu gostaria de ver o JQuery usando as mesmas idéias, partes da sintaxe; apenas modificado corretamente para o modelo de informação JSON.
StaxMan

1
Para quem procura uma implementação Ruby do JSONPath: github.com/joshbuddy/jsonpath
Robert Ross

@ GôTô: Usar o MongoDB, se você tiver essa liberdade, parece uma abordagem viável. (ver a resposta abaixo para um exemplo de como traduzir a consulta para o built-in shell)
serv-inc

48

Eu recomendaria meu projeto no qual estou trabalhando, chamado jLinq . Estou à procura de feedback para que eu esteja interessado em ouvir o que você pensa.

Se permite escrever consultas semelhantes às que você faria no 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)
        };
    });

Também é totalmente extensível!

A documentação ainda está em andamento, mas você ainda pode experimentá-la online.


@ hugoware: existe alguma documentação para isso. Existem outras que .starts () consultas (como contém?)
Rikki

5
Última atualização há 8 anos e nenhuma resposta a ser perguntado se o projeto está morto há 5 anos ... Acho que o projeto está morto.
cfc


14

O jmespath funciona realmente muito fácil e bem, http://jmespath.org/ Ele está sendo usado pela Amazon na interface de linha de comando da AWS, portanto, deve ser bastante estável.


5
No entanto, ao mesmo tempo na mesma página: "Se você precisar de recursos mais avançados que talvez não sejam possíveis com o --query, consulte o jq, um processador JSON da linha de comando." Parece que a AWS usa jmespathpara o --queryparâmetro, mas recomenda jqa tubulação da linha de comando. docs.aws.amazon.com/cli/latest/userguide/…
wisbucky

10

jq é um J SON q linguagem uery, destina-se principalmente para a linha de comando, mas com ligações a uma ampla gama de linguagens de programação (Java, Node.js, php, ...) e até mesmo disponíveis no navegador via jq-web .

Aqui estão algumas ilustrações baseadas na pergunta original, que deu esse JSON como exemplo:

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

SOMA (X) ONDE Y> 0 (equivaleria a 7)

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

LISTA (X) ONDE Y> 0 (equivaleria a [3,4])

map(.y > 0)

sintaxe jq estende a sintaxe JSON

Toda expressão JSON é uma expressão jq válida e expressões como [1, (1+1)]e {"a": (1 + 1)} `ilustram como o jq estende a sintaxe JSON.

Um exemplo mais útil é a expressão jq:

{a,b}

qual, dado o valor JSON {"a":1, "b":2, "c": 3}, avalia para {"a":1, "b":2}.


8

O array.filter()método interno torna obsoleta a maioria dessas chamadas bibliotecas de consultas javascript

Você pode colocar quantas condições dentro do delegado puder imaginar: comparação simples, iniciaCom, etc. Não testei, mas você provavelmente poderia aninhar filtros também para consultar coleções internas.


5
array.filter()faz parte do JavaScript, não do JSON.
Iain Samuel McLean Elder

2
JSON é um subconjunto de JavaScript, mas há muitas linguagens que suportam JSON e matrizes e que têm um método de filtro de matriz implementado, portanto esse é um ponto válido.
Dakab

7

Se você estiver usando .NET, o Json.NET suporta consultas LINQ na parte superior do JSON. Este post tem alguns exemplos. Ele suporta filtragem, mapeamento, agrupamento, etc.


7

O ObjectPath é uma linguagem de consulta simples e de grande largura para documentos JSON de estrutura complexa ou desconhecida. É semelhante ao XPath ou JSONPath, mas muito mais poderoso graças a cálculos aritméticos incorporados, mecanismos de comparação e funções internas.

Exemplo

A versão Python é madura e usada na produção. JS ainda está na versão beta.

Provavelmente, em um futuro próximo, forneceremos uma versão Javascript completa. Também queremos desenvolvê-lo ainda mais, para que ele possa servir como uma alternativa mais simples às consultas do Mongo.


1
Exceto que a documentação é praticamente inexistente, é difícil descobrir como fazer algo como encontrar elementos com texto como algo.
James O'Brien

1
@ JamesO'Brien Obrigado pela sua observação - se você achar a referência inútil e tiver algum problema específico em mente, informe-nos aqui - alguém tentará ajudar. No momento, estamos trabalhando para tornar os documentos mais utilizáveis. Adoraria seus comentários.
precisa

Obrigado, Eu agradeço. Eu gostaria de usar Atualmente, estou usando ashphy.com/JSONPathOnlineEvaluator ?
James O'Brien

Não foi possível descobrir como usar isso com Javascript devido a uma total falta de documentação.
user3670743

Estamos à procura de colaboradores para ajudar nisso. Você pode escrever no Github ou no google groups groups.google.com/forum/#!members/objectpath o que você está tentando alcançar, e tenho certeza de que alguém responderá suas perguntas.
Ela Bednarek

6

Outra maneira de analisar isso seria usar o mongoDB Você pode armazenar seu JSON no mongo e consultá-lo através da sintaxe de consulta do mongodb.


O MongoDB é tão bom de usar. Veja a resposta abaixo para um exemplo de como usar.
serv-inc

4

OK, este post é um pouco antigo, mas ... se você quiser fazer consultas semelhantes a SQL em JSON nativo (ou objetos JS) em objetos JS, dê uma olhada em https://github.com/deitch/searchjs

É uma linguagem jsql escrita inteiramente em JSON e uma implementação de referência. Você pode dizer: "Quero encontrar todos os objetos em uma matriz que tenham name ===" John "&& age === 25 como:

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

A implementação de referência searchjs funciona no navegador e também em um pacote npm do nó

npm install searchjs

Também pode fazer coisas como junções complexas e negação (NÃO). Ignora nativamente o caso.

Ainda não faz somatório ou conta, mas provavelmente é mais fácil fazê-lo lá fora.


3

Aqui estão algumas bibliotecas javascript simples que também farão o truque:

  • O Dollar Q é uma boa biblioteca leve. Ele tem uma sensação familiar da sintaxe de encadeamento popularizada pelo jQuery e é de apenas 373 SLOC.
  • O SpahQL é uma linguagem de consulta completa com uma sintaxe semelhante ao XPath ( Homepage , Github
  • jFunk é uma linguagem de consulta em andamento, com uma sintaxe semelhante aos seletores CSS / jQuery. Parecia promissor, mas não teve nenhum desenvolvimento além do comprometimento inicial.

  • (adicionado em 2014): a ferramenta de linha de comando jq tem uma sintaxe pura, mas infelizmente é uma biblioteca de arquivos de configuração. Exemplo de uso:

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


3

No MongoDB , é assim que funcionaria (no shell mongo, existem drivers para um idioma de sua escolha).

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"}}}]);

Os três primeiros comandos inserem os dados em sua coleção. (Basta iniciar o mongodservidor e conectar-se ao mongocliente.)

Os próximos dois processam os dados. $matchfiltros, $groupaplica o sume list, respectivamente.


2

O SpahQL é o mais promissor e bem pensado dentre eles, até onde eu sei. Eu recomendo dar uma olhada.


2


Acabei de terminar uma versão liberável de uma JS-lib do lado do cliente (defiant.js) que faz o que você está procurando. Com o defiant.js, é possível consultar uma estrutura JSON com as expressões XPath com as quais você está familiarizado (sem novas expressões de sintaxe como no JSONPath).

Exemplo de como funciona (veja no navegador aqui 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 você pode ver, o DefiantJS estende o objeto global JSON com uma função de pesquisa e a matriz retornada é entregue com funções agregadas. O DefiantJS contém algumas outras funcionalidades, mas essas estão fora do escopo deste assunto. Em qualquer lugar, você pode testar a lib com um XPath Evaluator do cliente. Acho que as pessoas não familiarizadas com o XPath acharão esse avaliador útil.
http://defiantjs.com/#xpath_evaluator

Mais informações sobre defiant.js
http://defiantjs.com/
https://github.com/hbi99/defiant.js

Espero que você ache útil ... Atenciosamente


Atualmente, é possível obter o caminho completo para os resultados?
XenSis 31/07

2
  1. O Google tem um projeto chamado lovefield ; acabei de descobrir sobre isso e parece interessante, apesar de estar mais envolvido do que apenas colocar sublinhado ou lodash.

    https://github.com/google/lovefield

Lovefield é um mecanismo de consulta relacional escrito em JavaScript puro. Ele também fornece ajuda com dados persistentes no lado do navegador, por exemplo, usando o IndexedDB para armazenar dados localmente. Ele fornece sintaxe semelhante a SQL e funciona em vários navegadores (atualmente compatível com Chrome 37+, Firefox 31+, IE 10+ e Safari 5.1 + ...


  1. Outra entrada recente interessante neste espaço chamada jinqJs .

    http://www.jinqjs.com/

    Analisando brevemente os exemplos , parece promissor e o documento da API parece estar bem 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 é uma biblioteca javaScript pequena, simples, leve e extensível que não possui dependências. O jinqJs fornece uma maneira simples de executar consultas como SQL em matrizes javaScript, coleções e serviços da web que retornam uma resposta JSON. O jinqJs é semelhante à expressão Lambda da Microsoft para .Net e fornece recursos semelhantes para consultar coleções usando um SQL como sintaxe e funcionalidade de predicado. O objetivo do jinqJs é fornecer uma experiência semelhante ao SQL para programadores familiarizados com as consultas LINQ.


1

Vou enfatizar a noção de apenas usar seu próprio javascript, mas para algo um pouco mais sofisticado, você pode olhar para os dados do dojo . Não o utilizou, mas parece que fornece aproximadamente o tipo de interface de consulta que você está procurando.


1

A implementação atual do Jaql tem como alvo o processamento de grandes dados usando um cluster Hadoop, portanto, pode ser mais do que você precisa. No entanto, ele é executado facilmente sem um cluster do Hadoop (mas ainda exige que o código do Hadoop e suas dependências sejam compilados, os quais geralmente são incluídos). Uma pequena implementação do Jaql que poderia ser incorporada em Javascript e no navegador seria uma ótima adição ao projeto.

Seus exemplos acima são facilmente escritos em 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]

Claro, também há muito mais. Por exemplo:

// 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 }}]

O Jaql pode ser baixado / discutido em http://code.google.com/p/jaql/


1

Você também pode usar o Underscore.js, que é basicamente uma biblioteca de facas suíças para manipular coleções. Usando _.filter, _.pluck, _.reducevocê pode fazer SQL-como consultas.

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

O Underscore.js funciona no lado do cliente e no servidor e é uma biblioteca notável.

Você também pode usar o Lo-Dash, que é um fork do Underscore.js com melhores desempenhos.


1

Sempre que possível, eu mudaria todas as consultas para o back-end no servidor (para o banco de dados SQL ou outro tipo de banco de dados nativo). O motivo é que será mais rápido e otimizado para fazer a consulta.

Eu sei que o jSON pode ser autônomo e pode haver +/- para ter uma linguagem de consulta, mas não vejo a vantagem se você estiver recuperando dados do back-end para um navegador, como na maioria dos casos de uso do JSON. Consulte e filtre no back-end para obter os dados mais pequenos necessários.

Se, por qualquer motivo, você precisar consultar no front-end (principalmente em um navegador), sugiro apenas o uso do array.filter (por que inventar outra coisa?).

Dito isto, o que eu acho que seria mais útil é uma API de transformação para json ... eles são mais úteis, pois depois que você tiver os dados, poderá exibi-los de várias maneiras. No entanto, novamente, você pode fazer muito disso no servidor (que pode ser muito mais fácil de escalar) do que no cliente - SE você estiver usando o servidor <--> modelo de cliente.

Apenas meus 2 centavos vale a pena!


1

Confira https://github.com/niclasko/Cypher.js (observação: eu sou o autor)

É uma implementação Javascript de dependência zero da linguagem de consulta do banco de dados de gráficos Cypher, juntamente com um banco de dados de gráficos. É executado no navegador (testado com Firefox, Chrome, IE).

Com relevância para a pergunta. Pode ser usado para consultar pontos de extremidade JSON:

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

Aqui está um exemplo de consulta a um documento JSON complexo e de análise:

Exemplo de consulta JSON Cypher.js


1

PythonQL oferece uma sintaxe embutido que IMHO é uma melhoria em SQL, principalmente porque group, window, where, let, etc, podem ser livremente misturados.

$ 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 mostra duas respostas diferentes para sua pergunta, dependendo da sua necessidade de lidar com toda a estrutura ou apenas com o valor. A execução fornece o resultado esperado.

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

0

Você poderia usar linq.js.

Isso permite usar agregações e seleções de um conjunto de dados de objetos, como outros dados de estruturas.

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>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.