Apakah ada bahasa query untuk JSON?


227

Apakah ada (kira-kira) bahasa SQL atau seperti XQuery untuk query JSON?

Saya sedang memikirkan kumpulan data yang sangat kecil yang memetakan dengan baik ke JSON di mana akan menyenangkan jika menjawab pertanyaan seperti "apa saja semua nilai X di mana Y> 3" atau untuk melakukan operasi tipe SUM / COUNT seperti biasa.

Sebagai contoh yang sepenuhnya dibuat-buat, sesuatu seperti ini:

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

Saya pikir ini akan bekerja baik sisi klien dan sisi server dengan hasil yang dikonversi ke struktur data spesifik bahasa yang sesuai (atau mungkin disimpan sebagai JSON)

Googling cepat menunjukkan bahwa orang-orang telah memikirkannya dan mengimplementasikan beberapa hal ( JAQL ), tetapi sepertinya itu bukan penggunaan standar atau sekumpulan perpustakaan yang telah muncul. Sementara setiap fungsi cukup sepele untuk diimplementasikan sendiri, jika seseorang telah melakukannya dengan benar, saya tidak ingin menemukan kembali roda.

Ada saran?

Sunting: Ini mungkin memang ide yang buruk atau JSON mungkin format yang terlalu umum untuk apa yang saya pikirkan .. Alasan menginginkan bahasa query alih-alih hanya melakukan penjumlahan / fungsi-fungsi langsung seperti yang diperlukan adalah bahwa saya berharap untuk membangun pertanyaan secara dinamis berdasarkan input pengguna. Agak suka argumen bahwa "kita tidak perlu SQL, kita bisa menulis fungsi yang kita butuhkan". Akhirnya yang keluar dari tangan atau Anda akhirnya menulis versi SQL Anda sendiri saat Anda mendorongnya semakin jauh. (Oke, saya tahu itu sedikit argumen yang konyol, tetapi Anda mendapatkan idenya ..)


Saya punya kebutuhan juga. Saya perlu mencocokkan permintaan JSON yang masuk dengan nilai tertentu di lokasi tertentu di pohon objek. Permintaan sebenarnya harus dikonfigurasi oleh pengguna (daya). Solusi saat ini adalah membangun XML make-shift dari JSON dan menerapkan XPath.
Vladimir Dyuzhev

1
Ini lebih dari alat shell, tetapi jq ( stedolan.github.io/jq ) telah luar biasa untuk menjelajahi data json. Cobalah di taman bermain: jqplay.org
jtmoulia

Ada alat berbasis web yang memungkinkan Anda untuk menjalankan kueri SQL pada umpan JSON publik atau API di sqall.co .
Stack Man


Jawaban:


91

Tentu, bagaimana dengan:

Mereka semua tampaknya sedikit bekerja dalam proses, tetapi bekerja sampai batas tertentu. Mereka juga mirip dengan XPath dan XQuery secara konseptual; meskipun XML dan JSON memiliki model konseptual yang berbeda (hierarkis vs objek / struct).

EDIT Sep-2015: Sebenarnya sekarang ada standar JSON Pointer yang memungkinkan traversal konten JSON yang sangat sederhana dan efisien. Ini tidak hanya ditentukan secara formal, tetapi juga didukung oleh banyak perpustakaan JSON. Jadi saya akan menyebutnya standar nyata yang sangat berguna, meskipun karena ekspresifitasnya yang terbatas, itu mungkin atau mungkin tidak dianggap Bahasa Query per se.


77
dengan kata lain, tidak ada yang standar dan stabil ... :-(
Vladimir Dyuzhev

Berbicara tentang standar, saya mendengar desas-desus bahwa XQuery 3.1 mungkin diperluas untuk mendukung permintaan JSON (mirip dengan JSONiq ). Tentu saja, ini bisa memakan waktu lama karena XQuery 3.0 belum dirilis secara resmi.
Julien Ribon

Ya ampun, saya harap tidak. Semua upaya XML-> JSON yang saya lihat adalah kekacauan yang mengerikan - model informasi tidak kompatibel. Tetapi saya ingin melihat JQuery menggunakan ide yang sama, bagian dari sintaks; hanya dimodifikasi dengan benar ke model info JSON.
StaxMan

1
Bagi siapa pun yang mencari implementasi Ruby JSONPath: github.com/joshbuddy/jsonpath
Robert Ross

@ GôTô: Menggunakan MongoDB, jika Anda memiliki kebebasan itu, sepertinya pendekatan yang layak. (lihat jawaban di bawah ini untuk contoh bagaimana menerjemahkan kueri ke shell bawaan)
serv-inc

48

Saya akan merekomendasikan proyek saya yang sedang saya kerjakan bernama jLinq . Saya mencari umpan balik sehingga saya tertarik mendengar pendapat Anda.

Jika memungkinkan Anda menulis kueri yang mirip dengan yang Anda lakukan di 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)
        };
    });

Ini sepenuhnya dapat diperpanjang juga!

Dokumentasinya masih dalam proses, tetapi Anda masih dapat mencobanya secara online.


@hugoware: apakah ada dokumentasi untuk ini? Apakah ada pertanyaan selain .starts () (seperti berisi?)
Rikki

5
Pembaruan terakhir 8 tahun yang lalu dan tidak ada tanggapan untuk ditanya apakah proyek sudah mati 5 tahun yang lalu ... Saya pikir proyek sudah mati.
cfc


14

jmespath bekerja sangat mudah dan baik, http://jmespath.org/ Ini sedang digunakan oleh Amazon di antarmuka baris perintah AWS, jadi itu harus cukup stabil.


5
Namun pada saat yang sama di halaman yang sama: "Jika Anda memerlukan fitur lebih lanjut yang tidak mungkin dengan --query, Anda dapat memeriksa jq, prosesor JSON baris perintah." Jadi sepertinya AWS menggunakan jmespathuntuk --queryparameter, tetapi merekomendasikan jquntuk pemipaan baris perintah. docs.aws.amazon.com/cli/latest/userguide/…
wisbucky

10

JQ adalah J SON q bahasa uery, terutama ditujukan untuk baris perintah tapi dengan binding untuk berbagai bahasa pemrograman (Java, node.js, php, ...) dan bahkan tersedia dalam browser melalui JQ-web .

Berikut adalah beberapa ilustrasi berdasarkan pertanyaan awal, yang memberikan JSON ini sebagai contoh:

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

SUM (X) WHERE Y> 0 (sama dengan 7)

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

LIST (X) WHERE Y> 0 (sama dengan [3,4])

map(.y > 0)

sintaks jq memperluas sintaks JSON

Setiap ekspresi JSON adalah ekspresi jq yang valid, dan ekspresi seperti [1, (1+1)]dan {"a": (1 + 1)} `menggambarkan bagaimana jq memperluas sintaks JSON.

Contoh yang lebih berguna adalah ekspresi jq:

{a,b}

yang, diberi nilai JSON {"a":1, "b":2, "c": 3}, dievaluasi menjadi {"a":1, "b":2}.


8

Built-in array.filter()metode membuat sebagian besar disebut perpustakaan permintaan javascript usang

Anda dapat menempatkan sebanyak mungkin kondisi di dalam delegasi seperti yang dapat Anda bayangkan: perbandingan sederhana, dimulai dengan, dll. Saya belum menguji tetapi Anda mungkin bisa menyaring filter juga untuk menanyakan koleksi dalam.


5
array.filter()adalah bagian dari JavaScript, bukan JSON.
Iain Samuel McLean Penatua

2
JSON adalah subset dari JavaScript, tetapi ada banyak bahasa yang mendukung JSON dan array dan yang memiliki metode filter array diimplementasikan, jadi ini adalah poin yang valid.
dakab

7

Jika Anda menggunakan .NET maka Json.NET mendukung kueri LINQ di atas JSON. Posting ini memiliki beberapa contoh. Ini mendukung penyaringan, pemetaan, pengelompokan, dll.


7

ObjectPath adalah bahasa query sederhana dan ligthweigth untuk dokumen JSON dari struktur yang kompleks atau tidak dikenal. Ini mirip dengan XPath atau JSONPath, tetapi jauh lebih kuat berkat perhitungan aritmatika tertanam, mekanisme perbandingan, dan fungsi bawaan.

Contoh

Versi python sudah matang dan digunakan dalam produksi. JS masih dalam versi beta.

Mungkin dalam waktu dekat kami akan menyediakan versi Javascript lengkap. Kami juga ingin mengembangkannya lebih lanjut, sehingga bisa berfungsi sebagai alternatif yang lebih sederhana untuk pertanyaan Mongo.


1
Kecuali itu hampir tidak memiliki dokumentasi, jadi sulit bagaimana mengetahui bagaimana melakukan sesuatu seperti menemukan elemen dengan teks seperti sesuatu.
James O'Brien

1
@ JamesO'Brien Terima kasih atas komentar Anda - jika Anda menemukan referensi tidak berguna dan memiliki masalah khusus, beri tahu kami di sini - seseorang akan mencoba membantu. Kami sedang berupaya membuat dokumen lebih bermanfaat, saya suka komentar Anda.
Ela Bednarek

Terima kasih - saya menghargainya. Saya ingin menggunakannya. Saat ini saya menggunakan ashphy.com/JSONPathOnlineEvaluator ?
James O'Brien

Tidak dapat menemukan cara menggunakannya dengan Javascript karena kurangnya dokumentasi.
user3670743

Kami mencari kontributor untuk membantu itu. Anda dapat menulis di Github atau grup google.google.com/forum/#!members/objectpath apa yang ingin Anda capai, dan saya yakin seseorang akan menjawab Qs Anda.
Ela Bednarek

6

Cara lain untuk melihatnya adalah dengan menggunakan mongoDB. Anda dapat menyimpan JSON Anda di mongo dan kemudian menanyakannya melalui sintaks permintaan mongodb.


MongoDB sangat bagus untuk digunakan. Lihat jawaban di bawah ini untuk contoh cara menggunakan.
serv-inc

4

OK, postingan ini agak lama, tapi ... jika Anda ingin melakukan query seperti SQL di JSON asli (atau objek JS) pada objek JS, lihat https://github.com/deitch/searchjs

Ini adalah bahasa jsql yang sepenuhnya ditulis dalam JSON, dan implementasi referensi. Anda dapat mengatakan, "Saya ingin menemukan semua objek dalam array yang memiliki nama ===" John "&& age === 25 sebagai:

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

Searchjs implementasi referensi bekerja di browser serta sebagai paket npm node

npm install searchjs

Itu juga dapat melakukan hal-hal seperti gabungan kompleks dan negasi (TIDAK). Ini secara asli mengabaikan kasus.

Itu belum melakukan penjumlahan atau penghitungan, tetapi mungkin lebih mudah untuk melakukannya di luar.


3

Berikut adalah beberapa pustaka javascript sederhana yang juga akan melakukan trik:

  • Dollar Q adalah perpustakaan ringan yang bagus. Ini memiliki rasa yang akrab dengan sintak rantai yang dipopulerkan oleh jQuery dan hanya 373 SLOC.
  • SpahQL adalah bahasa query berfitur lengkap dengan sintaksis yang mirip dengan XPath ( Beranda , Github
  • jFunk adalah bahasa permintaan sedang berlangsung, dengan sintaksis yang mirip dengan pemilih CSS / jQuery. Itu tampak menjanjikan, tetapi belum memiliki perkembangan di luar komitmen awal.

  • (ditambahkan 2014): alat baris perintah jq memiliki sintaks yang rapi, tetapi sayangnya itu adalah pustaka ac. Contoh penggunaan:

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


3

Di MongoDB , beginilah cara kerjanya (di mongo shell, ada driver untuk bahasa pilihan Anda).

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

Tiga perintah pertama memasukkan data ke dalam koleksi Anda. (Mulai saja mongodserver dan terhubung dengan mongoklien.)

Dua proses selanjutnya adalah data. $matchfilter, $groupterapkan sumdan list, masing-masing.


2

SpahQL adalah yang paling menjanjikan dan dipikirkan dengan baik dari ini, sejauh yang saya tahu. Saya sarankan untuk mengecek terlebih dahulu.


2


Saya baru saja menyelesaikan versi yang dapat dirilis dari JS-lib sisi klien (defiant.js) yang melakukan apa yang Anda cari. Dengan defiant.js, Anda dapat meminta struktur JSON dengan ekspresi XPath yang Anda kenal (tidak ada ekspresi sintaksis baru seperti pada JSONPath).

Contoh cara kerjanya (lihat di browser di sini 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

Seperti yang Anda lihat, DefiantJS memperluas JSON objek global dengan fungsi pencarian dan array yang dikembalikan dikirimkan dengan fungsi agregat. DefiantJS berisi beberapa fungsi lain tetapi itu berada di luar ruang lingkup untuk subjek ini. Siapa pun, Anda dapat menguji lib dengan XPath Evaluator di sisi klien. Saya pikir orang yang tidak terbiasa dengan XPath akan menganggap evaluator ini berguna.
http://defiantjs.com/#xpath_evaluator

Informasi lebih lanjut tentang defiant.js
http://defiantjs.com/
https://github.com/hbi99/defiant.js

Saya harap Anda menemukan itu berguna ... Salam


Apakah saat ini mungkin untuk mendapatkan path lengkap ke hasil?
XeniaSis

2
  1. Google memiliki proyek yang disebut lovefield ; baru tahu tentang itu, dan itu terlihat menarik, meskipun itu lebih terlibat daripada hanya jatuh di garis bawah atau lodash.

    https://github.com/google/lovefield

Lovefield adalah mesin kueri relasional yang ditulis dalam JavaScript murni. Ini juga menyediakan bantuan dengan data yang bertahan di sisi browser, misalnya menggunakan IndexedDB untuk menyimpan data secara lokal. Ini memberikan sintaks seperti SQL dan bekerja lintas-browser (saat ini mendukung Chrome 37+, Firefox 31+, IE 10+, dan Safari 5.1 + ...


  1. Entri terbaru yang menarik di ruang ini disebut jinqJs .

    http://www.jinqjs.com/

    Meninjau secara singkat contoh - contohnya , terlihat menjanjikan, dan dokumen API tampaknya ditulis dengan baik.


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 adalah pustaka javaScript kecil, sederhana, ringan dan dapat dikembangkan yang tidak memiliki dependensi. jinqJs menyediakan cara sederhana untuk melakukan query seperti SQL pada array javaScript, koleksi dan layanan web yang mengembalikan respons JSON. jinqJs mirip dengan ekspresi Lambda Microsoft untuk .Net, dan menyediakan kemampuan yang mirip dengan kueri koleksi menggunakan sintaksis seperti SQL dan fungsi predikat. Tujuan jinqJs adalah untuk memberikan pengalaman seperti SQL untuk programmer yang akrab dengan query LINQ.


1

Saya akan mendukung gagasan hanya menggunakan javascript Anda sendiri, tetapi untuk sesuatu yang sedikit lebih canggih Anda mungkin melihat data dojo . Belum pernah menggunakannya tetapi sepertinya itu memberi Anda sekitar jenis antarmuka permintaan yang Anda cari.


1

Implementasi Jaql saat ini menargetkan pemrosesan data besar menggunakan cluster Hadoop, jadi mungkin lebih dari yang Anda butuhkan. Namun, ini berjalan dengan mudah tanpa cluster Hadoop (tetapi masih membutuhkan kode Hadoop dan dependensinya untuk dikompilasi, yang sebagian besar termasuk). Implementasi kecil Jaql yang dapat tertanam dalam Javascript dan browser akan menjadi tambahan yang bagus untuk proyek ini.

Contoh Anda di atas mudah ditulis dalam 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]

Tentu saja, masih banyak lagi. Sebagai contoh:

// 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 dapat diunduh / didiskusikan di http://code.google.com/p/jaql/


1

Anda juga dapat menggunakan Underscore.js yang pada dasarnya adalah pustaka swiss-knife untuk memanipulasi koleksi. Menggunakan _.filter, _.pluck, _.reduceAnda dapat melakukan SQL seperti query.

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 berfungsi baik sisi klien dan sisi server dan merupakan pustaka terkenal.

Anda juga dapat menggunakan Lo-Dash yang merupakan cabang dari Underscore.js dengan kinerja yang lebih baik.


1

Bilamana mungkin saya akan menggeser semua query ke backend di server (ke SQL DB atau tipe database asli lainnya). Alasannya adalah karena akan lebih cepat dan lebih dioptimalkan untuk melakukan kueri.

Saya tahu bahwa JSON dapat berdiri sendiri dan mungkin ada +/- untuk memiliki bahasa query tetapi saya tidak dapat melihat keuntungannya jika Anda mengambil data dari backend ke browser, karena sebagian besar kasus penggunaan JSON. Permintaan dan filter di backend untuk mendapatkan data sekecil yang diperlukan.

Jika karena alasan apa pun Anda perlu melakukan query di front-end (kebanyakan di browser) maka saya sarankan hanya menggunakan array.filter (mengapa menemukan sesuatu yang lain?).

Yang mengatakan apa yang saya pikir akan lebih bermanfaat adalah transformasi API untuk json ... mereka lebih berguna karena setelah Anda memiliki data, Anda mungkin ingin menampilkannya dalam beberapa cara. Namun, sekali lagi, Anda dapat melakukan banyak hal ini di server (yang bisa lebih mudah untuk skala) daripada pada klien - JIKA Anda menggunakan server <--> model klien.

Hanya senilai 2 pence saya!


1

Lihat https://github.com/niclasko/Cypher.js (catatan: Saya penulisnya)

Ini adalah implementasi Javascript nol-dependensi dari bahasa query basis data grafik Cypher bersama dengan basis data grafik. Ini berjalan di browser (diuji dengan Firefox, Chrome, IE).

Dengan relevansi dengan pertanyaan. Ini dapat digunakan untuk menanyakan titik akhir JSON:

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

Berikut adalah contoh permintaan dokumen JSON yang kompleks dan melakukan analisis di atasnya:

Contoh permintaan JSON Cypher.js


1

PythonQL menawarkan sintaks tertanam yang IMHO adalah perbaikan pada SQL, terutama karena group, window, where, let, dll dapat dengan bebas bercampur.

$ 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))

Kode ini menunjukkan dua jawaban berbeda untuk pertanyaan Anda, tergantung pada kebutuhan Anda untuk menangani seluruh struktur atau hanya nilainya. Eksekusi memberi Anda hasil yang diharapkan.

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

0

Anda bisa menggunakannya linq.js.

Ini memungkinkan untuk menggunakan agregasi dan pemilihan dari kumpulan data objek, seperti data struktur lainnya.

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>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.