JSON için bir sorgu dili var mı?


227

JSON'u sorgulamak için (kabaca) SQL veya XQuery benzeri bir dil var mı?

Ben "Y> 3 nerede tüm X değerleri vardır" gibi sorulara kolayca cevap ya da her zamanki SUM / COUNT tipi işlemleri yapmak güzel olurdu JSON için harita çok küçük veri kümeleri düşünüyorum.

Tamamen oluşturulmuş örnek olarak, böyle bir şey:

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

Sonuçları uygun dile özgü veri yapısına dönüştürülen (veya belki de JSON olarak tutulur) bu hem istemci tarafı hem de sunucu tarafı işe yarayacağını düşünüyorum

Hızlı bir Google, insanların bunu düşündüklerini ve birkaç şey ( JAQL ) uyguladıklarını , ancak henüz standart bir kullanım veya kütüphane seti gibi görünmediğini gösteriyor. Her fonksiyon kendi başına uygulanması oldukça önemsiz olsa da, birisi zaten doğru yaptıysa, tekerleği yeniden icat etmek istemiyorum.

Baska öneri?

Düzenleme: Bu gerçekten kötü bir fikir olabilir veya JSON ne düşündüğüm için çok genel bir biçim olabilir .. Sadece doğrudan gerektiği gibi summing / etc işlevlerini yerine bir sorgu dili isteyen nedeni ben inşa etmeyi umuyoruz sorguları dinamik olarak kullanıcı girdisine dayalıdır. “SQL'e ihtiyacımız yok, sadece ihtiyacımız olan fonksiyonları yazabiliriz” argümanı gibi. Sonunda ya kontrolden çıkar ya da daha ileriye doğru iterken kendi SQL sürümünüzü yazabilirsiniz. (Tamam, bunun biraz aptalca bir argüman olduğunu biliyorum, ama fikri anladın ..)


Benim de böyle bir ihtiyacım var. Nesne ağacındaki belirli konumlarda belirli değerlere göre gelen JSON isteklerini eşleştirmek gerekiyor. Sorgu aslında bir (güçlü) kullanıcı tarafından yapılandırılmalıdır. Geçerli geçici çözüm, JSON dışında bir make-shift XML oluşturmak ve XPath uygulamaktır.
Vladimir Dyuzhev

1
Daha çok bir kabuk aracıdır, ancak jq ( stedolan.github.io/jq ) json verilerini keşfetmek için harikaydı . Oyun alanında deneyin: jqplay.org
jtmoulia

Sqall.co adresindeki genel JSON yayınlarında veya API'larında SQL sorguları çalıştırmanıza izin veren web tabanlı bir araç vardır .
Stack Man


Yanıtlar:


91

Tabii, nasıl olur:

Hepsi devam etmekte olan bir iş gibi görünüyor ama bir dereceye kadar çalışıyor. Kavramsal olarak XPath ve XQuery'ye de benzerler; XML ve JSON'un farklı kavramsal modelleri olsa da (hiyerarşik ve nesne / yapı).

Eylül 2015 EDIT : Aslında artık JSON içeriğinin çok basit ve verimli bir şekilde geçişine izin veren JSON Pointer standardı var. Yalnızca resmi olarak belirtilmez, aynı zamanda birçok JSON kütüphanesi tarafından da desteklenir. Bu yüzden, gerçek anlamda kullanışlı standart diyebilirim, ancak sınırlı ifadesi nedeniyle, sorgulama dili olarak düşünülebilir veya görülmeyebilir.


77
Başka bir deyişle, standart ve kararlı bir şey yok ... :-(
Vladimir Dyuzhev

Standart hakkında konuşmak gerekirse , XQuery 3.1'in JSON sorgularını ( JSONiq'e benzer ) desteklemek için genişletilebileceği yönünde bir söylenti duydum . Tabii ki, XQuery 3.0 henüz resmi olarak yayınlanmadığından biraz zaman alabilir.
Julien Ribon

Rahmet, kesinlikle umarım. Gördüğüm tüm XML-> JSON girişimleri korkunç karışıklıklar oldu - bilgi modelleri uyumsuz. Ama ben aynı fikirleri, sözdiziminin bölümlerini kullanarak JQuery görmek istiyorum; sadece JSON bilgi modeline uygun şekilde değiştirildi.
StaxMan

1
JSONPath'in Ruby uygulamasını arayan herkes için: github.com/joshbuddy/jsonpath
Robert Ross

@ GôTô: Eğer bu özgürlüğe sahipseniz MongoDB'yi kullanmak uygulanabilir bir yaklaşım gibi görünüyor. ( sorgunun yerleşik kabuğa nasıl çevrileceğine ilişkin bir örnek için aşağıdaki cevaba bakın )
serv-inc

48

Üzerinde çalıştığım projeyi jLinq olarak öneriyorum . Geri bildirim arıyorum, bu yüzden ne düşündüğünü duymak isterim.

LINQ'dakine benzer sorgular yazmanıza izin verirse ...

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

Tamamen genişletilebilir!

Belgeler hala devam ediyor, ancak yine de çevrimiçi olarak deneyebilirsiniz.


@hugoware: bunun için herhangi bir belge var mı? .Starts () (içerir gibi) dışında herhangi bir sorgu var mı?
Rikki

5
Son güncelleme 8 yıl önce ve projenin 5 yıl önce öldüğü sorulmasına hiçbir yanıt yok ... Bence proje öldü.
cfc


14

jmespath gerçekten çok kolay ve iyi çalışıyor, http://jmespath.org/ Amazon tarafından AWS komut satırı arayüzünde kullanılıyor, bu yüzden oldukça kararlı olmalı.


5
Yine de aynı sayfada: "--query ile mümkün olmayan daha gelişmiş özelliklere ihtiyacınız varsa, bir komut satırı JSON işlemcisi olan jq'a göz atabilirsiniz." Öyleyse AWS parametre jmespathiçin kullanıyor --query, ancak jqkomut satırı borulaması için öneriyor . docs.aws.amazon.com/cli/latest/userguide/…
wisbucky

10

jq , çoğunlukla komut satırı için tasarlanmış, ancak çok çeşitli programlama dillerine (Java, node.js, php, ...) bağlanan ve hatta jq-web aracılığıyla tarayıcıda bulunan bir J SON q uery dilidir .

İşte bu JSON'u örnek olarak veren orijinal soruya dayanan bazı çizimler:

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

TOPLA (X) Y> 0 (7'ye eşittir)

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

LIST (X) Y> 0 ([3,4] 'e eşittir)

map(.y > 0)

jq sözdizimi JSON sözdizimini genişletir

Her JSON ifadesi geçerli bir jq ifadesidir ve [1, (1+1)]ve {"a": (1 + 1)} ` gibi ifadeler, jq'nin JSON sözdizimini nasıl genişlettiğini gösterir.

Daha kullanışlı bir örnek jq ifadesidir:

{a,b}

JSON değeri verildiğinde {"a":1, "b":2, "c": 3}değerlendirilir {"a":1, "b":2}.


8

Yerleşik array.filter()yöntem , sözde javascript sorgu kitaplıklarının çoğunu geçersiz kılar

Delege içine hayal edebildiğiniz kadar çok koşul koyabilirsiniz: basit karşılaştırma, startsWith, vb. Test etmedim, ancak muhtemelen iç koleksiyonları sorgulamak için filtreleri de iç içe yerleştirebilirsiniz.


5
array.filter()JavaScript'in bir parçasıdır, JSON değil.
Iain Samuel McLean Elder

2
JSON, JavaScript'in bir alt kümesidir, ancak hem JSON hem de dizileri destekleyen ve bir dizi filtre yöntemi uygulanmış birçok dil vardır, bu nedenle bu geçerli bir noktadır.
dakab


7

ObjectPath , karmaşık veya bilinmeyen yapıdaki JSON belgeleri için basit ve ışıksız sorgulama dilidir. XPath veya JSONPath'e benzer, ancak gömülü aritmetik hesaplamalar, karşılaştırma mekanizmaları ve yerleşik işlevler sayesinde çok daha güçlüdür.

Misal

Python versiyonu olgun ve üretimde kullanılıyor. JS hala beta sürümündedir.

Muhtemelen yakın gelecekte tam teşekküllü bir Javascript sürümü sunacağız. Ayrıca, Mongo sorgularına daha basit bir alternatif olarak hizmet edebilmesi için daha da geliştirmek istiyoruz.


1
Bunun dışında herhangi bir belgeye sahip olması dışında, bir şey gibi metin içeren öğeleri bulmak gibi bir şeyi nasıl yapacağınızı bulmak zordur.
James O'Brien

1
@ JamesO'Brien Yorumunuz için teşekkürler - referansı işe yaramaz bulursanız ve aklınızda herhangi bir sorun varsa, bize buradan bildirin - biri yardım etmeye çalışacaktır. Şu anda dokümanları daha kullanışlı hale getirmek için çalışıyoruz, yorumlarınızı çok isterim.
Ela Bednarek

Teşekkürler bunun için minnettarım. Kullanmak istiyorum. Şu anda ashphy.com/JSONPathOnlineEvaluator kullanıyorum ?
James O'Brien

Toplam dokümantasyon eksikliği nedeniyle bunun Javascript ile nasıl kullanılacağını anlayamadım.
user3670743

Bu konuda yardımcı olacak katkılar arıyoruz. Github veya google groups groups.google.com/forum/#!members/objectpath üzerine ne elde etmeye çalıştığınızı yazabilirsiniz ve eminim birileri sorularınıza cevap verecektir.
Ela Bednarek

6

Buna bakmak için başka bir yol mongoDB kullanmak olacaktır JSON mongo saklamak ve sonra mongodb sorgu sözdizimi ile sorgulayabilirsiniz.


MongoDB'nin kullanımı çok güzel. Bkz aşağıda cevabını nasıl kullanılacağına ilişkin bir örnek için.
serv-inc

4

Tamam, bu yazı biraz eski, ama ... JS nesnelerinde yerel JSON (veya JS nesneleri) içinde SQL benzeri bir sorgu yapmak istiyorsanız, https://github.com/deitch/searchjs adresine bir göz atın.

Hem tamamen JSON'da yazılmış bir jsql dilidir hem de bir referans uygulamasıdır. "Bir dizideki adı ===" John "&& age === 25 olan bir nesneyi bulmak istiyorum:

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

Referans uygulama searchjs tarayıcıda ve bir düğüm npm paketi olarak çalışır

npm install searchjs

Ayrıca karmaşık birleşimler ve olumsuzlama (NOT) gibi şeyler de yapabilir. Yerel olarak durumu yok sayar.

Henüz toplama veya sayma yapmaz, ancak dışarıda bunları yapmak daha kolaydır.


3

İşte hile yapacak bazı basit javascript kütüphaneleri:

  • Dolar Q hoş bir hafif kütüphanedir. JQuery tarafından popüler hale getirilen zincirleme sözdizimine aşina bir his var ve sadece 373 SLOC.
  • SpahQL , XPath'e benzer bir sözdizimine sahip tam özellikli bir sorgu dilidir ( Ana Sayfa , Github
  • jFunk , CSS / jQuery seçicilerine benzer bir sözdizimiyle devam eden bir sorgu dilidir. Umut verici görünüyordu, ancak ilk taahhütte ötesinde herhangi bir gelişme olmadı.

  • (2014 eklendi): jq komut satırı aracının düzgün bir sözdizimi vardır, ancak ne yazık ki ac kütüphanesidir. Örnek kullanım:

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


3

In MongoDB , işte bu (Mongo kabuk, istediğiniz bir dil için sürücüler orada var) çalışma şekli şöyledir.

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

İlk üç komut, verileri koleksiyonunuza ekler. (Sadece mongodsunucuyu başlatın ve mongoistemciye bağlanın .)

Sonraki iki veri işliyor. $matchfiltreleri sırasıyla $groupuygular sumve list.


2

SpahQL, bunlardan en umut verici ve iyi düşünülmüş. Kesinlikle kontrol etmenizi öneririz.


2


Az önce aradığınızı yapan bir istemci tarafı JS-lib (defiant.js) 'nin serbest bırakılabilir bir versiyonunu bitirdim. Defiant.js ile bir JSON yapısını tanıdığınız XPath ifadeleriyle sorgulayabilirsiniz (JSONPath'te olduğu gibi yeni sözdizimi ifadeleri yoktur).

Nasıl çalıştığına bir örnek ( http://defiantjs.com/defiant.js/demo/sum.avg.htm adresindeki tarayıcıya bakın ):

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

Gördüğünüz gibi, DefiantJS genel nesne JSON'u bir arama işleviyle genişletir ve döndürülen dizi, toplama işlevleriyle teslim edilir. DefiantJS birkaç başka işlevsellik içerir, ancak bunlar bu konunun kapsamı dışındadır. İsterseniz, lib'i bir istemci tarafı XPath Değerlendiricisi ile test edebilirsiniz. Bence XPath'a aşina olmayan insanlar bu değerlendiriciyi faydalı bulacaktır.
http://defiantjs.com/#xpath_evaluator

Defiant.js hakkında daha fazla bilgi
http://defiantjs.com/
https://github.com/hbi99/defiant.js

Umarım faydalı bulursun ...


Sonuçların tam yolunu bulmak şu anda mümkün mü?
XeniaSis

2
  1. Google'ın lovefield adlı bir projesi var ; sadece bunu öğrendim ve ilginç görünüyor, ancak alt çizgiye veya lodash'a düşmekten daha çok ilgili.

    https://github.com/google/lovefield

Lovefield, saf JavaScript ile yazılmış ilişkisel bir sorgu motorudur. Ayrıca, tarayıcı tarafında verilerin sürekli kalmasına yardımcı olur, örneğin verileri yerel olarak depolamak için IndexedDB'yi kullanma. Sağladığı sözdizimi SQL benzeri ve şu anda Chrome 37+, Firefox 31+ IE 10 ve üstü sürümleri ve Safari 5.1 + desteği sunan çapraz tarayıcı (çalışır ...


  1. Bu alana jinqJ adı verilen bir başka ilginç giriş .

    http://www.jinqjs.com/

    Örnekleri kısaca gözden geçirmek umut verici görünüyor ve API belgesi iyi yazılmış gibi görünüyor.


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 bağımlılığı olmayan küçük, basit, hafif ve genişletilebilir bir javaScript kütüphanesidir. jinqJs, bir JSON yanıtı döndüren javaScript dizileri, koleksiyonları ve web hizmetlerinde SQL benzeri sorgular gerçekleştirmek için basit bir yol sağlar. jinqJs, Microsoft'un .Net için Lambda ifadesine benzer ve SQL benzeri bir sözdizimi ve yüklem işlevselliği kullanarak koleksiyonları sorgulamak için benzer özellikler sağlar. jinqJs'in amacı, LINQ sorgularına aşina olan programcılara SQL benzeri bir deneyim sunmaktır.


1

Sadece kendi javascriptinizi kullanma fikrini ikinciyim, ancak biraz daha sofistike bir şey için dojo verilerine bakabilirsiniz . Kullanmadım ama kabaca aradığınız sorgu arabirimi türünü veriyor gibi görünüyor.


1

Mevcut Jaql uygulaması, bir Hadoop kümesi kullanarak büyük veri işlemeyi hedeflediğinden, ihtiyacınız olandan daha fazla olabilir. Bununla birlikte, bir Hadoop kümesi olmadan kolayca çalışır (ancak yine de çoğunlukla dahil olan Hadoop kodu ve bağımlılıklarının derlenmesini gerektirir). Javascript ve tarayıcıya gömülebilen küçük bir Jaql uygulaması projeye harika bir ek olacaktır.

Yukarıdaki örnekleriniz jaql ile kolayca yazılmıştır:

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

Tabii ki, çok daha fazlası var. Örneğin:

// 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, http://code.google.com/p/jaql/ adresinden indirilebilir / tartışılabilir.


1

Ayrıca koleksiyonları işlemek için temelde bir swiss-knife kütüphanesi olan Underscore.js'yi de kullanabilirsiniz . Kullanılması _.filter, _.pluck, _.reducesen sorguları SQL benzeri yapabilirsiniz.

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 hem istemci hem de sunucu tarafında çalışır ve dikkate değer bir kitaplıktır.

Daha iyi performanslara sahip bir Underscore.js çatalı olan Lo-Dash'i de kullanabilirsiniz .


1

Mümkün olduğunda tüm sorgulamayı sunucudaki arka uca kaydırırdım (SQL DB veya diğer yerel veritabanı türüne). Nedeni sorgulama yapmak için daha hızlı ve daha optimize olacak olmasıdır.

JSON tek başına olabilir ve bir sorgulama dili olması için +/- olabilir biliyorum ama JSON kullanım durumlarının çoğu gibi arka uçtan bir tarayıcıya veri alıyorsanız avantajı göremiyorum. Gerekli veriyi küçültmek için arka uçta sorgulayın ve filtreleyin.

Herhangi bir nedenle ön uç (çoğunlukla bir tarayıcıda) sorgulamak gerekiyorsa, o zaman ben sadece array.filter kullanmanızı öneririz (neden başka bir şey icat?).

Ben daha yararlı olacağını düşündüğüm json için bir dönüşüm API olduğunu söyledi ... onlar bir kez verilere sahip birkaç kez görüntülemek isteyebilirsiniz çünkü onlar daha yararlı. Bununla birlikte, yine, sunucuda (ölçeklendirmek çok daha kolay olabilir) sunucuda bunu yapabilirsiniz - eğer sunucu <--> istemci modeli kullanıyorsanız.

Sadece benim 2 peni değer!


1

Https://github.com/niclasko/Cypher.js adresine göz atın (not: Ben yazarım)

Bir grafik veritabanı ile birlikte Cypher grafik veritabanı sorgu dilinin sıfır bağımlılıklı bir Javascript uygulamasıdır. Tarayıcıda çalışır (Firefox, Chrome, IE ile test edilmiştir).

Soruyla alakalı. JSON uç noktalarını sorgulamak için kullanılabilir:

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

Karmaşık bir JSON belgesini sorgulamak ve üzerinde analiz yapmak için bir örnek:

Cypher.js JSON sorgu örneği


1

PythonQL IMHO SQL üzerinde bir gelişme olduğunu gömülü bir sözdizimi sunuyor, esas nedeni group, window, where, let, vb serbestçe karışmış olabilir.

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

Bu kod, tüm yapıyı veya sadece değeri ele almanız gerektiğine bağlı olarak sorunuzun iki farklı cevabını gösterir. Yürütme size beklenen sonucu verir.

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

0

Kullanabilirsin linq.js.

Bu, diğer yapı verileri olarak, bir nesne veri kümesinden toplamaların ve seçimlerin kullanılmasına izin verir.

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.