ChatGPT解决这个技术问题 Extra ChatGPT

JSON 是否有查询语言?

是否有(大致)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 版本,因为您将其推得越来越远。 (好吧,我知道这是一个有点愚蠢的论点,但你明白了..)

我也有这样的需求。我需要通过对象树中特定位置的特定值来匹配传入的 JSON 请求。查询实际上必须由(高级)用户配置。当前的解决方法是使用 JSON 构建临时 XML 并应用 XPath。
它更像是一个 shell 工具,但 jq (stedolan.github.io/jq) 非常适合探索 json 数据。在操场上试一试:jqplay.org
有一个基于 Web 的工具,可让您在 sqall.co 上对公共 JSON 供稿或 API 运行 SQL 查询。

C
Community

当然,怎么样:

json路径。

json查询

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

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


换句话说,没有什么标准和稳定的...... :-(
谈到标准,我听说 XQuery 3.1 可能会扩展为支持 JSON 查询(类似于 JSONiq)。当然,这可能需要一些时间,因为 XQuery 3.0 还没有正式发布。
哦,怜悯,我绝对希望不会。我见过的所有 XML->JSON 尝试都是可怕的混乱——信息模型不兼容。但我希望看到 JQuery 使用相同的想法,部分语法;刚刚正确修改为 JSON 信息模型。
对于正在寻找 JSONPath 的 Ruby 实现的任何人:github.com/joshbuddy/jsonpath
@GôTô:如果您有这种自由,使用 MongoDB 似乎是一种可行的方法。 (有关如何将查询转换为内置 shell 的示例,请参阅 answer below
d
dkretz

I'd recommend my project I'm working on called 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)
        };
    });

它也是完全可扩展的!

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


@hugoware:有没有这方面的文档。除了 .starts() 是否还有其他查询(例如包含?)
最后一次更新是 8 年前,并且没有回应被问到该项目是否在 5 年前死了……我认为该项目已经死了。
是的,好像死了。链接现在是 404。JMESPath 似乎非常健壮、标准化和跨平台,但不确定它是否可以像 jLinq 那样进行连接。
J
Jonathan

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

该列表正在增长:

JSONiq(基于 XQuery)

UNQL(如 SQL)

JaQL(函数式)

JsonPath(类似 XPath)

Json Query(类似于 XPath)

GraphQL(基于模板,类型化)


S
Simon East

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(', ', @)

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


但同时在同一页面上:“如果您需要使用 --query 可能无法实现的更高级功能,您可以查看 jq,一个命令行 JSON 处理器。”因此,AWS 似乎将 jmespath 用于 --query 参数,但建议将 jq 用于命令行管道。 docs.aws.amazon.com/cli/latest/userguide/…
+1 JMESPath - 这是一个非常全面和详细的规范,具有多种语言的库,以及相对简单和直观的语法。
p
peak

jq 是一种 JSON query 语言,主要用于命令行,但绑定到多种编程语言(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}


f
forivall

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

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


array.filter() 是 JavaScript 的一部分,而不是 JSON。
JSON 是 JavaScript 的一个子集,但是有很多语言同时支持 JSON 和数组,并且实现了数组过滤器方法,所以这是一个有效的观点。
虽然您的答案是正确的,即 filter() 可用于“查询”JSON 对象,但有一个缺点:它接受函数而不是字符串。因此,您不能通过网络使用它作为参数传递。
J
James Newton-King

如果您使用的是 .NET,那么 Json.NET 支持基于 JSON 的 LINQ 查询。这个post有一些例子。它支持过滤、映射、分组等。


f
forivall

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


MongoDB 非常好用。有关如何使用的示例,请参见 answer below
正要提出同样的建议。 docs.mongodb.com/manual/tutorial/query-documents
E
Ela Bednarek

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

https://i.stack.imgur.com/G2d5K.png

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

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


除了它几乎没有任何文档,因此很难找出如何做任何事情,比如查找带有文本之类的元素。
@JamesO'Brien 感谢您的评论 - 如果您发现 reference 无用并且有任何具体问题,请告诉我们here - 有人会尽力提供帮助。我们目前正在努力使文档更可用,我希望您能提出意见。
谢谢,我很感激。我想用。目前我正在使用 ashphy.com/JSONPathOnlineEvaluator
由于完全缺乏文档,无法弄清楚如何将其与 Javascript 一起使用。
我们正在寻找贡献者来帮助解决这个问题。您可以在 Github 或 google 群组 groups.google.com/forum/#!members/objectpath 上写下您想要实现的目标,我相信有人会回答您的问题。
d
deitch

好的,这篇文章有点老了,但是……如果您想在 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) 之类的操作。它本机忽略大小写。

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


m
mohammad pakivand

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


f
forivall

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

Dollar Q 是一个不错的轻量级库。它对 jQuery 流行的链接语法有一种熟悉的感觉,并且只有 373 SLOC。

SpahQL 是一种功能齐全的查询语言,其语法类似于 XPath (Homepage, Github

jFunk 是一种进行中的查询语言,其语法类似于 CSS/jQuery 选择器。它看起来很有希望,但除了最初的提交之外没有任何发展。

(2014 年添加):jq 命令行工具语法简洁,但不幸的是它是 ac 库。示例用法:< package.json jq '.dependencies | to_entry | .[] |选择(.value | 开始(“git”)) | 。钥匙'


s
serv-inc

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


N
Niclas Kjäll-Ohlsson

查看 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 query example


只是想知道,为什么你需要做到这一点?
谢谢你的提问。学习、乐趣和生产力:-)
N
Nina Scholz

您可以使用 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( ));


D
David

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


H
Hakan Bilgin

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

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


目前是否有可能获得结果的完整路径?
m
mg1075

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


A
Anthony Tomasic

PythonQL 提供了一种嵌入式语法,恕我直言,这是对 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 的概念,但对于更复杂的东西,您可以查看 dojo data。没用过,但看起来它为您提供了您正在寻找的大致那种查询界面。


佚名

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


M
Michel Hua

您还可以使用 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 的一个分支,具有更好的性能。


C
Colin Saxton

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

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

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

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

只值我的 2 便士!