是否有(大致)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),但它似乎还没有一个标准的用法或库集出现。虽然单独实现每个功能都是相当琐碎的,但如果有人已经做对了,我就不想重新发明轮子。

有什么建议吗?

Edit: This may indeed be a bad idea or JSON may be too generic a format for what I'm thinking.. The reason for wanting a query language instead of just doing the summing/etc functions directly as needed is that I hope to build the queries dynamically based on user-input. Kinda like the argument that "we don't need SQL, we can just write the functions we need". Eventually that either gets out of hand or you end up writing your own version of SQL as you push it further and further. (Okay, I know that is a bit of a silly argument, but you get the idea..)


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


编辑 2022 年 9 月:

JMESPath似乎是使用最广泛、增长最快、评价最好的替代方案。它有很多功能,包括“where”风格的过滤器。

原:

当然可以,这样怎么样:

JsonPath。 Json查询

它们似乎都在进行中,但在某种程度上是有效的。它们在概念上也类似于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。NET支持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" && age===25 as:

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

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

npm install searchjs

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

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


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

这个名单还在增加:

JSONiq(基于XQuery) UNQL(类似SQL) JaQL(功能) JsonPath(于xpath) Json查询(类似于xpath) GraphQL(基于模板,类型化)


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

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


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


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

Dollar Q is a nice lightweight library. It has a familiar feel to the chaining syntax made popular by jQuery and is only 373 SLOC. SpahQL is a fully featured query language with a syntax similar to XPath (Homepage, Github jFunk is an in progress query language, with a syntax similar to CSS/jQuery selectors. It looked promising, but hasn't had any development beyond its in initial commit. (added 2014): the jq command line tool has a neat syntax, but unfortunately it is a c library. Example usage: < package.json jq '.dependencies | to_entries | .[] | select(.value | startswith("git")) | .key'


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


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

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

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


我刚刚完成了一个客户端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

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

我希望它对你有用…… 问候


你也可以使用Underscore.js,它基本上是一个瑞士刀库来操作集合。使用_。过滤器,_。勇气,_。减少你可以做类似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的一个分支,性能更好。


谷歌有一个项目叫lovefield;刚刚发现了它,它看起来很有趣,尽管它比键入下划线或lodash更复杂。 https://github.com/google/lovefield

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


这个领域最近出现的另一个有趣的条目叫做jinqJs。 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 is a small, simple, lightweight and extensible javaScript library that has no dependencies. jinqJs provides a simple way to perform SQL like queries on javaScript arrays, collections and web services that return a JSON response. jinqJs is similar to Microsoft's Lambda expression for .Net, and it provides similar capabilities to query collections using a SQL like syntax and predicate functionality. jinqJs’s purpose is to provide a SQL like experience to programmers familiar with LINQ queries.


只要有可能,我就会将所有查询转移到服务器的后端(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分别应用sum和list。


jq是一种JSON查询语言,主要用于命令行,但绑定到广泛的编程语言(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文档并对其进行分析的示例:

js JSON查询示例


你可以使用linq.js。

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

var data = [{x: 2, y: 0}, {x: 3 y: 1}, {x: 4, y: 1}); // sum (x) where y > 0 -> console.log (Enumerable.From(数据)其中(" $。y > 0").Sum("$.x")); // list (x) where y > 0 -> [3,4] console.log (Enumerable.From(数据)其中(" $。y > 0").Select("$.x").ToArray()); < script src = " https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js " > < /脚本>


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

$ 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对象= {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(对象,路径));


如果你使用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