245

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

我正在考虑可以很好地映射到 JSON 的非常小的数据集,在其中很容易回答诸如“Y > 3 时 X 的所有值是多少”之类的查询,或者执行通常的 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 可能是我所想的过于通用的格式。想要一种查询语言而不是根据需要直接执行 summing/etc 函数的原因是我希望构建根据用户输入动态查询。有点像“我们不需要 SQL,我们可以编写我们需要的函数”的论点。最终,要么失控,要么您最终编写自己的 SQL 版本,因为您将其推得越来越远。(好吧,我知道这是一个有点愚蠢的论点,但你明白了..)

4

23 回答 23

103

当然,怎么样:

它们似乎都在进行中,但在某种程度上都在起作用。它们在概念上也类似于 XPath 和 XQuery;即使 XML 和 JSON 具有不同的概念模型(分层与对象/结构)。

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

于 2009-04-24T18:28:41.613 回答
50

我会推荐我正在从事的名为 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)
        };
    });

它也是完全可扩展的!

文档仍在进行中,但您仍然可以在线尝试。

于 2009-04-29T14:49:03.643 回答
49

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

该列表正在增长:

于 2011-10-18T18:42:44.523 回答
18

JMESPath 工作起来非常简单而且效果很好:http: //jmespath.org/。它有一个完整的规范和多种语言的库。Amazon 在 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(', ', @)

您可以在docs中使用更多实时示例。

于 2015-09-06T07:34:04.957 回答
16

jq是一种J SON查询语言,主要用于命令行,但绑定到多种编程语言(Java、node.js、php...),甚至可以通过jq-web在浏览器中使用。jq 基于 C 的实现通常称为“jq”,基于 Go 的版本称为“gojq”

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

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

SUM(X) 其中 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}

于 2018-03-04T01:28:25.450 回答
10

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

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

于 2012-02-17T04:21:41.533 回答
7

如果您使用的是 .NET,那么Json.NET支持 JSON 之上的 LINQ 查询。这篇文章有一些例子。它支持过滤、映射、分组等。

于 2009-04-26T02:24:46.563 回答
7

另一种看待这种情况的方法是使用mongoDB您可以将 JSON 存储在 mongo 中,然后通过 mongodb 查询语法对其进行查询。

于 2012-11-08T19:12:43.147 回答
7

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

例子

Python 版本成熟并用于生产。JS 仍处于测试阶段。

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

于 2013-06-23T00:15:16.560 回答
4

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

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

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

参考实现 searchjs 在浏览器以及节点 npm 包中工作

npm install searchjs

它还可以执行复杂连接和否定 (NOT) 之类的操作。它本机忽略大小写。

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

于 2011-08-11T13:03:05.287 回答
4

如果你想使用纯 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));

于 2020-11-21T16:47:02.447 回答
3

这里有一些简单的 JavaScript 库也可以解决问题:

  • Dollar Q是一个不错的轻量级库。它对 jQuery 流行的链接语法有一种熟悉的感觉,并且只有 373 SLOC。
  • SpahQL是一种功能齐全的查询语言,其语法类似于 XPath ( Homepage , Github
  • jFunk是一种进行中的查询语言,其语法类似于 CSS/jQuery 选择器。它看起来很有希望,但除了最初的提交之外没有任何发展。

  • (2014 年添加):jq 命令行工具语法简洁,但不幸的是它是 ac 库。示例用法:

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

于 2012-12-03T21:42:54.720 回答
3

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

于 2015-09-16T11:57:32.303 回答
3

查看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 文档并对其执行分析的示例:

Cypher.js JSON 查询示例

于 2019-04-30T22:23:26.510 回答
3

你可以使用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>

于 2019-06-30T09:53:37.447 回答
2

据我所知,SpahQL 是其中最有前途和经过深思熟虑的。我强烈建议检查一下。

于 2013-01-27T14:49:01.803 回答
2


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

它是如何工作的示例(在浏览器中查看它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

如您所见,DefiantJS 使用搜索函数扩展了全局对象 JSON,返回的数组通过聚合函数传递。DefiantJS 包含一些其他功能,但这些功能超出了本主题的范围。任何人,您都可以使用客户端 XPath Evaluator 测试该库。我认为不熟悉 XPath 的人会发现这个评估器很有用。
http://defiantjs.com/#xpath_evaluator

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

我希望你觉得它有用......问候

于 2014-01-02T10:55:16.103 回答
2
  1. Google 有一个名为lovefield的项目;刚刚发现它,它看起来很有趣,尽管它比仅仅添加下划线或 lodash 更复杂。

    https://github.com/google/lovefield

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


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

于 2015-04-30T02:06:18.137 回答
2

PythonQL 提供了一种嵌入式语法,恕我直言,这是对 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
于 2020-03-07T18:37:08.480 回答
1

我将支持仅使用您自己的 javascript 的概念,但对于更复杂的东西,您可能会查看dojo data。没用过,但看起来它为您提供了您正在寻找的大致那种查询界面。

于 2009-04-22T14:42:02.403 回答
1

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

您上面的示例很容易用 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/下载/讨论

于 2009-04-24T21:11:24.437 回答
1

您还可以使用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

Underscore.js 适用于客户端和服务器端,是一个值得注意的库。

您还可以使用Lo-Dash,它是 Underscore.js 的一个分支,具有更好的性能。

于 2014-05-24T20:13:32.757 回答
1

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

我知道 JSON 可以是独立的,并且可能有 +/- 用于查询语言,但如果您将数据从后端检索到浏览器,我看不到优势,就像大多数 JSON 用例一样。在后端查询和过滤以获取所需的尽可能小的数据。

如果出于某种原因您需要在前端查询(主要是在浏览器中),那么我建议只使用 array.filter (为什么要发明其他东西?)。

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

只值我的 2 便士!

于 2015-06-12T11:28:17.590 回答