Groupby и узел LINQ js

Я использую node-linq и пытаюсь понять GroupBy, но документации так мало

например, у меня есть эти данные:

{дата: 26.06.2013, имя: А, номер: 1}

{Дата: 26.06.2013, имя: А, номер: 5}

{дата: 27.06.2013, имя: Б, номер: 4}

{дата: 27.06.2013, имя: А, номер: 4}

и я хочу написать как этот запрос, но с LINQ для узла js

SELECT date, name, SUM(number)
FROM data
GROUPBY date, name

Я пробую этот код, но получаю ошибки

var o = new LINQ(data)
        .Select(function(name,d) {return name.statement,d.date;})
        .SUM((function(x) {return x.number;)
        .GroupBy(function(name,d) {return name.statement,d.date;}
    .ToArray()
                

есть ли у кого-нибудь какие-либо предложения или просто несколько примеров о GroupBy? Спасибо


person dardar.moh    schedule 27.06.2013    source источник
comment
Даже не думайте о LINQ как о SQL; это действительно не помогает.   -  person Callum Rogers    schedule 27.06.2013


Ответы (2)


Хотя вы можете видеть, что в README на github есть .GroupBy, .GroupBy нет, когда вы делаете npm install node-linq. Так что вам придется установить модуль с

npm install https://github.com/wearefractal/node-linq/tarball/master

Это ваши данные:

var LINQ = require('node-linq').LINQ;

var data = [ { date: '2013/06/26', name: 'A', number: 1 },
             { date: '2013/06/26', name: 'A', number: 5 },
             { date: '2013/06/27', name: 'B', number: 4 },
             { date: '2013/06/27', name: 'A', number: 4 } ];

Во-первых, вы хотите сгруппировать их. К сожалению, группировать по хешу нельзя, поэтому придется использовать суррогатный ключ:

var o = new LINQ(data).GroupBy(function(row) { return row.date + '~' + row.name; });
console.log(o);

Это результат:

{ '2013/06/26~A':
   [ { date: '2013/06/26', name: 'A', number: 1 },
     { date: '2013/06/26', name: 'A', number: 5 } ],
  '2013/06/27~B': [ { date: '2013/06/27', name: 'B', number: 4 } ],
  '2013/06/27~A': [ { date: '2013/06/27', name: 'A', number: 4 } ] }

Затем вы хотите суммировать числа, но не можете.

console.log(o.__proto__); // {}

Возможно, вам нужно обернуть его в LINQ?

new LINQ(o); // InvalidCastException: Data not Array

Неа.

Превратим объект в массив, потеряв ключи. В JavaScript нет Object.values(), поэтому мы должны сделать это следующим образом:

o = new LINQ(Object.keys(o).map(function(key) { return o[key] }));

Теперь мы можем, наконец, просуммировать все числа:

o = o.Select(function(rows) { return { date: rows[0].date, name: rows[0].name, sum: new LINQ(rows).Sum(function(row) { return row.number; }) } }).ToArray();
console.log(o);

Вот результат:

[ { date: '2013/06/26', name: 'A', sum: 6 },
  { date: '2013/06/27', name: 'B', sum: 4 },
  { date: '2013/06/27', name: 'A', sum: 4 } ]

Не очень красиво.

Подчеркивать

npm install underscore

Вот как сгруппировать данные с помощью библиотеки underscore.

var _ = require('underscore')._;

var data = [ { date: '2013/06/26', name: 'A', number: 1 },
             { date: '2013/06/26', name: 'A', number: 5 },
             { date: '2013/06/27', name: 'B', number: 4 },
             { date: '2013/06/27', name: 'A', number: 4 } ];

var grouper = function(row) { return row.date + '~' + row.name; };
var summer = function(rows) { return rows.reduce(function(sum, row) { return sum + row.number; }, 0); };

var o  = _.chain(data)
          .groupBy(grouper)
          .map(function(rows) { return { date: rows[0].date, name: rows[0].name, sum: summer(rows) }; })
          .value();

console.log(o); // same result

По-моему, гораздо приятнее.

person mak    schedule 27.06.2013
comment
Я так понял большое спасибо за помощь, код работает на 100% - person dardar.moh; 27.06.2013

В вашем коде есть некоторые ошибки:

  • Функции обратного вызова принимают только один аргумент, а не два.
  • В Node (и Javascript), если вы хотите вернуть несколько элементов, поместите их в объект или массив (например, оберните {})
  • Ваши фигурные скобки и круглые скобки не совпадают в нескольких случаях.

Например, вместо:

.Select(function(name,d) {return name.statement,d.date;})

вы должны написать:

.Select(function(item) { return { name: item.name, date: item.date } } )

и вместо:

.GroupBy(function(name,d) {return name.statement,d.date;}

вы должны написать:

.GroupBy(function(item) { return { name: item.name, date: item.date } } )

Однако GroupBy не реализована для асинхронной ссылки, как указано в примечаниях вверху файла ALINQ.coffee (# TODO: GroupBy, ContainsAll)

И ECMAScript до 6 не имеет большой стрелки => лямбда-нотации стиля, поэтому вам придется использовать некоторые комбинации карты и уменьшения, чтобы достичь той же функциональности, насколько мне известно, что, вероятно, будет означать улучшение узла -linq с такой возможностью.

Самое близкое, что вы можете получить, используя node-linq прямо сейчас, вероятно, что-то вроде этого:

var statement = [{"date":"2013/06/26","name":"A","number":1},
{"date":"2013/06/26","name":"A","number":5},
{"date":"2013/06/27","name":"B","number":4},
{"date":"2013/06/27","name":"A","number":4}]

var o = new LINQ(statement)
        .Select(function(item) {
               return {
                   date: item.date,
                   name: item.name, 
                   sum: new LINQ(statement).Sum(function(item){return item.number;})
               };
        })
        .OrderBy(function(item) {
               return [item.name, item.date];
         })
        .ToArray();

console.log(o);

который дает:

[ { date: '2013/06/26', name: 'A', sum: 14 },
  { date: '2013/06/26', name: 'A', sum: 14 },
  { date: '2013/06/27', name: 'A', sum: 14 },
  { date: '2013/06/27', name: 'B', sum: 14 } ]

Чтобы исправить часть суммы, используйте карту и уменьшите. Например, вы можете изучить lambda-js: https://github.com/dfellis/lambda-js< /а>

person Matt Mullens    schedule 27.06.2013