โหนด Groupby และ LINQ js

ฉันใช้ node-linq และพยายามทำความเข้าใจ GroupBy แต่เอกสารประกอบมีน้อยมาก

เช่นฉันมีข้อมูลนี้:

{วันที่:26/06/2013 ชื่อ:A หมายเลข:1}

{วันที่:26/06/2013 ชื่อ:A หมายเลข:5}

{วันที่:27/06/2013 ชื่อ:B หมายเลข:4}

{วันที่:27/06/2013 ชื่อ:A หมายเลข: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)


แม้ว่าคุณจะเห็นว่ามี .GroupBy ใน README บน github แต่ก็ไม่มี .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

ไม่.

มาแปลงวัตถุเป็นอาร์เรย์โดยการสูญเสียคีย์ ไม่มี Object.values() ใน JavaScript ดังนั้นเราจึงต้องทำดังนี้:

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, ประกอบด้วยทั้งหมด)

และ ECMAScript ก่อนหน้า 6 ไม่มีลูกศรขนาดใหญ่ => สัญลักษณ์ lambda สไตล์ ดังนั้นคุณจะต้องใช้ map ร่วมกันและลดขนาดเพื่อให้ได้ฟังก์ชันการทำงานแบบเดียวกันเท่าที่ฉันทราบ ซึ่งอาจหมายถึงการปรับปรุงโหนด -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