Вопрос

Существует ли (примерно) язык, подобный 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)

Быстрый поиск в Google показывает, что люди подумали об этом и внедрили несколько вещей (ДЖАКЛ), но не похоже, что стандартное использование или набор библиотек еще не появились.Хотя каждая функция довольно тривиальна для реализации сама по себе, если кто-то уже сделал это правильно, я не хочу заново изобретать колесо.

Есть какие-нибудь предложения?

Редактировать:Возможно, это действительно плохая идея, или JSON может быть слишком общим форматом для того, о чем я думаю..Причина, по которой нужен язык запросов вместо того, чтобы просто выполнять функции суммирования / etc напрямую по мере необходимости, заключается в том, что я надеюсь динамически создавать запросы на основе пользовательского ввода.Вроде как аргумент о том, что "нам не нужен SQL, мы можем просто написать нужные нам функции".В конце концов, это либо выходит из-под контроля, либо вы заканчиваете тем, что пишете свою собственную версию SQL, продвигая ее все дальше и дальше.(Ладно, я знаю, что это немного глупый аргумент, но вы уловили идею ..)

Это было полезно?

Решение

Конечно, как насчет:

Все они кажутся немного незавершенными, но в какой-то степени работают.Они также концептуально похожи на XPath и XQuery;несмотря на то, что XML и JSON имеют разные концептуальные модели (иерархические по сравнению с object / struct).

Редактировать Сентябрь-2015:На самом деле сейчас есть Указатель JSON стандарт, который позволяет очень простой и эффективный обход содержимого JSON.Он не только формально задан, но и поддерживается многими библиотеками JSON.Поэтому я бы назвал это настоящим полезным стандартом, хотя из-за его ограниченной выразительности он может считаться, а может и не считаться Языком запросов как таковым.

Другие советы

Я бы порекомендовал свой проект, над которым я работаю, под названием jLinq.Я ищу обратную связь, поэтому мне было бы интересно услышать, что вы думаете.

If позволяет вам писать запросы, аналогичные тем, которые вы делали бы в 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)
        };
    });

Это тоже полностью расширяемый!

Документация все еще находится в стадии разработки, но вы все еще можете попробовать это онлайн.

Обновить: XQuery 3.1 может запрашивать либо XML, либо JSON - или оба вместе.И XPath 3.1 тоже могу.

Список растет:

jmespath работает действительно довольно просто и хорошо, http://jmespath.org/ Он используется Amazon в интерфейсе командной строки AWS, так что он должен быть достаточно стабильным.

Встроенный array.filter() способ делает большинство этих так называемых библиотек запросов javascript устаревшими

Вы можете поместить в делегат столько условий, сколько сможете себе представить:простое сравнение, StartsWith и т.д.Я не тестировал, но вы, вероятно, могли бы также вложить фильтры для запроса внутренних коллекций.

Путь к объекту это простой и легковесный язык запросов для JSON-документов сложной или неизвестной структуры.Он похож на XPath или JSONPath, но гораздо более мощный благодаря встроенным арифметическим вычислениям, механизмам сравнения и встроенным функциям.

Example

Версия Python является зрелой и используется в производстве.JS все еще находится в стадии бета-тестирования.

Вероятно, в ближайшем будущем мы предоставим полноценную версию Javascript.Мы также хотим развивать его дальше, чтобы он мог служить более простой альтернативой запросам Mongo.

jq является JSON qпользовательский язык, в основном предназначенный для командной строки, но с привязками к широкому спектру языков программирования (Java, node.js, php, ...) и даже доступный в браузере через jq-веб.

Вот несколько иллюстраций, основанных на исходном вопросе, в котором в качестве примера был приведен этот JSON:

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

СУММА (X) ГДЕ Y > 0 (будет равно 7)

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

СПИСОК (X), ГДЕ 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}.

Если вы используете .NET, то Json.NET поддерживает запросы LINQ поверх JSON.Это Публикация имеет несколько примеров.Он поддерживает фильтрацию, сопоставление, группировку и т.д.

Другим способом взглянуть на это было бы использовать MongoDB Вы можете сохранить свой JSON в mongo, а затем запросить его с помощью синтаксиса запроса mongodb.

Ладно, этот пост немного устарел, но...если вы хотите выполнить SQL-подобный запрос в собственном JSON (или JS objects) для объектов JS, взгляните на https://github.com/deitch/searchjs

Это одновременно и язык jsql, полностью написанный на JSON, и эталонная реализация.Вы можете сказать: "Я хочу найти все объекты в массиве, которые имеют имя ==="Джон" && возраст ===25 как:

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

Эталонная реализация searchjs работает в браузере, а также в качестве пакета node npm

npm install searchjs

Он также может выполнять такие вещи, как сложные соединения и отрицание (NOT).Он изначально игнорирует регистр.

Он еще не выполняет суммирование или подсчет, но, вероятно, это проще сделать снаружи.

Вот несколько простых библиотек javascript, которые также помогут с этим:

  • Доллар Q это хорошая легкая библиотека.Он имеет знакомый синтаксис цепочки, ставший популярным благодаря jQuery, и имеет всего 373 SLOC.
  • SpahQL ( СпахКЛ ) это полнофункциональный язык запросов с синтаксисом , похожим на XPath (Домашняя страница, Гитхаб
  • Джфанк это разрабатываемый язык запросов с синтаксисом, похожим на селекторы CSS / jQuery.Это выглядело многообещающе, но не получило никакого развития за пределами начальной фиксации.

  • (добавлено в 2014 году):в инструмент командной строки jq имеет аккуратный синтаксис, но, к сожалению, это библиотека языка Си.Пример использования:

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

В MongoDB, вот как это будет работать (в оболочке mongo существуют драйверы для языка по вашему выбору).

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, соответственно.

SpahQL - самый многообещающий и хорошо продуманный из них, насколько я могу судить.Я настоятельно рекомендую проверить это.


Я только что закончил выпускаемую версию клиентской JS-библиотеки (defiant.js), которая делает то, что вы ищете.С помощью defiant.js вы можете запросить структуру JSON с помощью знакомых вам выражений XPath (без новых синтаксических выражений, как в 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.Я думаю, что люди, не знакомые с XPath, найдут этот оценщик полезным.
http://defiantjs.com/#xpath_evaluator

Дополнительная информация о defiant.js
http://defiantjs.com/
https://github.com/hbi99/defiant.js

Я надеюсь, вы найдете это полезным...С уважением

  1. У Google есть проект под названием лавфилд;только что узнал об этом, и это выглядит интересно, хотя это сложнее, чем просто добавить подчеркивание или Lodash.

    https://github.com/google/lovefield

Lovefield - это механизм реляционных запросов, написанный на чистом JavaScript.Это также предоставляет помощь с сохранением данных на стороне браузера, напримериспользование IndexedDB для локального хранения данных.Это обеспечивает SQL-подобный синтаксис и работает в разных браузерах (в настоящее время поддерживает Chrome 37+, Firefox 31+, IE 10+ и Safari 5.1+...


  1. Еще одна интересная недавняя запись в этом пространстве называется Джинкджс.

    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 предоставляет простой способ выполнять SQL-подобные запросы к массивам JavaScript, коллекциям и веб- сервисам, которые возвращают ответ в формате JSON.jinqJs похож на Microsoft Лямбда-выражение для .Net и предоставляет аналогичные возможности коллекции запросов, использующие синтаксис, подобный SQL, и функциональность предикатов.Цель jinqJs - предоставить программистам интерфейс, подобный SQL знакомый с запросами LINQ.

Я поддержу идею простого использования вашего собственного javascript, но для чего-то более сложного вы могли бы взглянуть на данные додзе.Я им не пользовался, но, похоже, он предоставляет вам примерно тот тип интерфейса запроса, который вы ищете.

Текущая реализация Jaql нацелена на обработку больших объемов данных с использованием кластера Hadoop, поэтому их может быть больше, чем вам нужно.Тем не менее, он легко запускается без кластера Hadoop (но по-прежнему требует компиляции кода Hadoop и его зависимостей, которые в основном включены).Небольшая реализация Jaql, которая могла бы быть встроена в Javascript и браузер a, стала бы отличным дополнением к проекту.

Приведенные выше ваши примеры легко написаны на 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/

Вы также можете использовать 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 работает как на стороне клиента, так и на стороне сервера и является примечательной библиотекой.

Вы также можете использовать Ло-Тире который является ответвлением от Underscore.js с лучшими характеристиками.

Всякий раз, когда это было возможно, я бы перенес все запросы на серверную часть на сервере (в базу данных SQL или другой собственный тип базы данных).Причина в том, что выполнение запросов будет более быстрым и оптимизированным.

Я знаю, что jSON может быть автономным, и может быть + / - за наличие языка запросов, но я не вижу преимущества, если вы извлекаете данные из серверной части в браузер, как в большинстве случаев использования JSON.Запрашивайте и фильтруйте в серверной части, чтобы получить как можно меньше необходимых данных.

Если по какой-либо причине вам нужно выполнить запрос во внешнем интерфейсе (в основном в браузере), то я бы предложил просто использовать array.filter (зачем изобретать что-то еще?).

Тем не менее, я думаю, что было бы более полезно использовать API преобразования для json...они более полезны, поскольку, получив данные, вы можете захотеть отобразить их несколькими способами.Однако, опять же, вы можете многое из этого делать на сервере (который может быть намного проще масштабировать), чем на клиенте - если вы используете server<--> клиентская модель.

Всего на мои 2 пенса дороже!

Проверьте https://github.com/niclasko/Cypher.js (примечание:Я автор)

Это Javascript-реализация языка запросов к базе данных Cypher graph с нулевой зависимостью наряду с базой данных graph.Он запускается в браузере (тестировался с Firefox, Chrome, IE).

Имеющий отношение к данному вопросу.Он может быть использован для запроса конечных точек JSON:

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

Вот пример запроса сложного JSON-документа и выполнения его анализа:

Cypher.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>

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top