JSON有查询语言吗?

是否有(大致)SQL或类似xquery的语言来查询JSON?

我正在考虑非常小的数据集,很好地映射到JSON,它将很容易回答查询,如“X的所有值是什么,Y > 3”或做通常的SUM / COUNT类型操作。

作为一个完全虚构的例子,是这样的:

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

我认为这将在客户端和服务器端工作,结果将被转换为适当的特定于语言的数据结构(或者可能保留为JSON)

快速谷歌搜索表明,人们已经考虑过它并实现了一些东西(JAQL),但它似乎还没有一个标准的用法或库集出现。虽然单独实现每个功能都是相当琐碎的,但如果有人已经做对了,我就不想重新发明轮子。

有什么建议吗?

编辑:这可能确实是一个坏主意或JSON可能是一个太通用的格式,我的想法。之所以需要一种查询语言,而不是根据需要直接执行求和/etc函数,是因为我希望基于用户输入动态地构建查询。有点像“我们不需要SQL,我们只需要编写我们需要的函数”的论点。最终,这要么失去控制,要么你最终会编写自己的SQL版本,因为你不断地推动它。(好吧,我知道这是一个有点愚蠢的论点,但你明白我的意思..)

193122 次浏览

我同意只使用自己的javascript,但对于更复杂的东西,你可能会看dojo数据。还没有使用过,但看起来它大致提供了您正在寻找的那种查询接口。

2022年9月编辑:

JMESPath似乎是最广泛使用,增长最快的的选项。它有很多特点,包括"where"风格过滤器

原:

当然可以,这样怎么样:

它们似乎都在进行中,但在某种程度上是有效的。它们在概念上也类似于XPath和XQuery;尽管XML和JSON有不同的概念模型(层次结构vs对象/结构)。

2015年9月:

实际上,现在有了JSON指针标准,允许非常简单有效地遍历JSON内容。它不仅是正式指定的,而且许多JSON库也支持它。所以我将它称为真正有用的标准,尽管由于其表达能力有限,它本身可能被认为是查询语言,也可能不被认为是查询语言。

当前的Jaql实现目标是使用Hadoop集群进行大型数据处理,因此可能超出了您的需求。然而,它可以在没有Hadoop集群的情况下轻松运行(但仍然需要编译Hadoop代码及其依赖项,其中大部分都包括在内)。Jaql的一个小实现可以嵌入到Javascript和浏览器中,这将是对项目的一个很好的补充。

上面的例子很容易用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]

当然,还有更多。例如:

// 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/下载/讨论

如果你使用的是。net,那么Json。网支持JSON之上的LINQ查询。这个帖子有一些例子。它支持过滤、映射、分组等。

我推荐我正在做的项目jLinq。我在寻求反馈,所以我很有兴趣听听你的想法。

如果让你写查询类似于你会在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)
};
});

它也是完全可扩展的!

文档仍在编写中,但您仍然可以在线尝试。

好吧,这篇文章有点老了,但是……如果你想用原生JSON(或JS对象)对JS对象进行类似sql的查询,请查看https://github.com/deitch/searchjs

它既是一种完全用JSON编写的jsql语言,也是一种参考实现。你可以说"我想找到数组中所有对象name==="John" &&25岁= = =:

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

参考实现searchjs可以在浏览器中工作,也可以作为节点npm包工作

npm install searchjs

它还可以做复杂连接和否定(NOT)之类的事情。它本身就忽略了大小写。

它还没有做求和或计数,但在外面做这些可能更容易。

更新:XQuery 3.1可以查询XML或JSON -或同时查询两者。XPath 3.1也可以。

这个名单还在增加:

内置的array.filter()方法使大多数所谓的javascript查询库过时

你可以在委托中放入尽可能多的条件:简单的比较,startsWith,等等。我还没有测试过,但是您可能也可以嵌套过滤器来查询内部集合。

另一种方法是使用mongoDB。你可以将JSON存储在mongodb中,然后通过mongodb查询语法进行查询。

下面是一些简单的javascript库,也可以做到这一点:

  • 美元的问是一个很好的轻量级库。它有一种由jQuery流行起来的链接语法的熟悉感觉,并且只有373 SLOC。
  • SpahQL是一种功能齐全的查询语言,其语法类似于XPath (主页Github . xml)
  • jFunk是一种正在进行的查询语言,其语法类似于CSS/jQuery的选择器。它看起来很有前途,但除了最初的承诺之外,没有任何发展。

  • (2014年添加):Jq命令行工具具有简洁的语法,但不幸的是它是一个c库。使用示例:

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

据我所知,SpahQL是其中最有前途、考虑最周全的一种。我强烈建议大家去看看。

ObjectPath是一种简单而轻量级的查询语言,适用于结构复杂或未知的JSON文档。它类似于XPath或JSONPath,但由于嵌入了算术计算、比较机制和内置函数,它的功能要强大得多。

Example .

Python版本已经成熟,已用于生产环境。JS仍处于测试阶段。

在不久的将来,我们可能会提供一个完整的Javascript版本。我们还想进一步开发它,以便它可以作为Mongo查询的一个更简单的替代品。

< p >
我刚刚完成了一个客户端JS-lib (defy .js)的可发布版本,它可以满足您的需求。使用defy .js,您可以使用您熟悉的XPath表达式(没有像JSONPath中那样的新语法表达式)查询JSON结构

它如何工作的例子(在浏览器中查看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
如你所见,defantjs用搜索函数扩展了全局对象JSON,返回的数组用聚合函数传递。defantjs包含一些其他功能,但这些超出了本主题的范围。 无论如何,您都可以使用客户端XPath评估器测试库。我认为不熟悉XPath的人会发现这个求值器很有用 http://defiantjs.com/#xpath_evaluator < / p >

更多关于defy .js的信息
.js http://defiantjs.com/
https://github.com/hbi99/defiant.js < / p >

我希望你觉得它有用… 关于< / p >

你也可以使用Underscore.js,它基本上是一个瑞士刀库来操作集合。使用_.filter_.pluck_.reduce可以执行类似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

js可以在客户端和服务器端工作,是一个著名的库。

你也可以使用Lo-Dash,它是性能更好的Underscore.js的一个分支。

  1. 谷歌有一个名为lovefield的项目;刚刚发现了它,它看起来很有趣,尽管它比键入下划线或lodash更复杂。

    https://github.com/google/lovefield < / p >

Lovefield是一个用纯JavaScript编写的关系查询引擎。它 还提供了在浏览器端持久化数据的帮助。 使用IndexedDB本地存储数据。它提供类似sql的语法和 跨浏览器工作(目前支持Chrome 37+, Firefox 31+, IE Safari 5.1+…


  1. 最近在这个空间中另一个有趣的条目叫做jinqJs

    < a href = " http://www.jinqjs.com/ " rel =“nofollow”> http://www.jinqjs.com/ < / >

    简单回顾一下例子,它看起来很有前途,而且API文档似乎写得很好


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是一个小的,简单的,轻量级的,可扩展的javaScript 没有依赖项的库。jinqJs提供了一种简单的方法 在javaScript数组、集合和web上执行SQL查询 返回JSON响应的服务。jinqJs与微软的类似 .Net的Lambda表达式,它提供与。net类似的功能 使用类似SQL的语法和谓词功能查询集合。 jinqJs的目的是为程序员提供类似SQL的体验 熟悉LINQ查询

只要有可能,我就会将所有查询转移到服务器的后端(SQL DB或其他本地数据库类型)。原因是这样查询会更快更优化。

我知道jSON可以是独立的,对于查询语言可能有+/-,但如果您从后端检索数据到浏览器,我看不出它的优势,因为大多数jSON用例都是这样。在后端进行查询和筛选,以获得所需的尽可能小的数据。

如果出于某种原因,你需要在前端进行查询(主要是在浏览器中),那么我建议只使用数组。过滤器(为什么要发明其他东西?)

也就是说,我认为更有用的是json的转换API…它们更有用,因为一旦你有了数据,你可能想要以多种方式显示它。但是,同样,您可以在服务器上完成这些工作(这比在客户端上更容易扩展)—如果您使用的是server<——>客户端模型。

只值我的两便士!

JMESPath工作真的很简单,很好:http://jmespath.org/。 它有一个完整的规范和多种语言的库。亚马逊正在AWS命令行界面中使用它,所以它必须非常稳定

语法的例子:

// Select a single item
people[1].firstName


// Select a slice of an array
people[0:5]


// Select all the first names
people[*].firstName


// Select all first names based on search term
people[?state=='VA'].firstName


// Count how many people are over 35
length(people[?age>`35`])


// Select only the name and age of people over 35
people[?age>`35`].{name: name, age: age}


// Join expressions together to sort and join elements into a string
people[?state == 'WA'].name | sort(@) | join(', ', @)

的文档中还有很多你可以使用的实例。

MongoDB中,这就是它的工作方式(在mongo shell中,存在你所选择的语言的驱动程序)。

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

前三个命令将数据插入到集合中。(只需启动mongod服务器并连接mongo客户端。)

接下来的两个处理数据。$match过滤器,$group分别应用sumlist

金桥是一种JSON uery语言,主要用于命令行,但绑定到广泛的编程语言(Java, node.js, php,…),甚至可以通过jq-web在浏览器中使用。基于c语言的jq实现通常被称为"jq",基于go语言的版本被称为“gojq"

以下是基于原始问题的一些插图,以JSON为例:

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

SUM(X) WHERE Y >0(等于7)

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

LIST(X) WHERE Y >0(等于[3,4])

map(.y > 0)

jq语法扩展了JSON语法

每个JSON表达式都是一个有效的jq表达式,诸如[1, (1+1)]和{"a":(1+1)} '这样的表达式说明了jq如何扩展JSON语法。

一个更有用的例子是jq表达式:

{a,b}

给定JSON值{"a":1, "b":2, "c": 3},其计算结果为{"a":1, "b":2}

查看https://github.com/niclasko/Cypher.js(注意:我是作者)

它是Cypher图形数据库查询语言和图形数据库的零依赖Javascript实现。它运行在浏览器(测试与Firefox, Chrome, IE)。

与问题相关。它可以用来查询JSON端点:

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

下面是一个查询复杂JSON文档并对其进行分析的示例:

<一个href = " https://niclasko.github.io/CypherJS/?load%20json%20from%20%22https: / / raw.githubusercontent.com/niclasko/niclasko.github.io/master/data/week_2018_38.json%22%20as%20l%20with%20collect (l) % 20 % 20行% 20解除% 20行% 20 % 20行% 20解除% 20行[% 27值% 27]% 20 % 20 v % 20 % 20行[0].datasource % 20 % 20数据源,% 20 row.key [0] .en % 20 % 20系列,% 20收集(% 7 bd: % 20 v [0] % 20 v: % 20 v [1] % 7 d) % 20 % 20 c % 20方差(v [1]) % 20 % 20 series_std_dev % 20笔(v[1]) /计数(1)% 20 % 20 series_avg % 20解除% 20 c % 20 % 20 e % 20 return%20datasource,%20series,%20tostring(todate(e.d))%20as%20date,%20e.v%20as%20val,%20(e.v-series_avg)/series_std_dev%20as%20val_z_score,%20series_std_dev,%20series_avg" rel="nofollow noreferrer"> cypherer .js JSON查询示例

你可以使用linq.js

这允许从对象的数据集中使用聚合和选择,就像其他结构数据一样。

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>

PythonQL提供了一种嵌入式语法,IMHO是对SQL的改进,主要是因为groupwindowwherelet等可以自由混合。

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


这段代码显示了您的问题的两个不同答案,这取决于您需要处理整个结构或仅处理值。执行会给你预期的结果。

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

如果你想使用纯javascript试试这个:

var object = { result: { data: { point1: "x", value: 2 }, foo: { bar: 7 } } },
path = 'result.data.value',
getValue = (o, p) => p.split('.').reduce((r, k) => r[k], o);


console.log(getValue(object, path));

如果你使用python, MongoDB有迷你开源版本, MontyDB https://github.com/davidlatwe/montydb 它在github上有超过500多颗星,并且得到了JetBrains的支持
from montydb.utils import MontyList
response = [
{'namespace': 'dash_mantine_components',
'props': {'checked': True,
'id': {'index': 0, 'type': 'checkbox'},
'label': 'My first to do'},
'type': 'Checkbox'},
{'namespace': 'dash_mantine_components',
'props': {'checked': True,
'id': {'index': 1, 'type': 'checkbox'},
'label': 'My Another to do'},
'type': 'Input'},
{'namespace': 'dash_mantine_components',
'props': {'checked': False,
'id': {'index': 2, 'type': 'checkbox'},
'label': 'My next level to do'},
'type': 'Div'},
]


cli = MontyList(response)
cli.find({'props.checked': True},{'type':1})

输出:

MontyList([{'type': 'Checkbox'}, {'type': 'Input'}])

与其他jsonquery选项相比,我更喜欢这个库,因为这个库提供了与MongoDB相同的感觉。

我是JSON的一种新的查询语言的开发者,叫做~Q(发音为" unquery")。它旨在解决其他JSON查询语言的许多缺点,并平衡易用性和表达能力。作为主要开发者,我当然是有偏见的,但你可以自己看看并决定:

https://github.com/xcite-db/Unquery

对于OP的例子,~Q中的查询将是:

{
"example1:[]" : "$sum(x)?y>0",
"example2:[]" : ["x?y>0"]
}

我使用SQLite来实现:https://sqlite.org/json1.html

这很好,因为你可以使用实际 SQL语言,SQLite非常快。

首先我创建一个临时表:

create temp table data as select value from json_each(readfile('data.json'))

然后使用SQLite JSON函数:

select value->'$.foo' foo, count(value->'$.bar') nbar from data group by foo