如何访问 RowDataPacket 对象

103

我目前正在使用Node-webkit开发桌面应用程序。在此过程中,我需要从本地MySQL数据库获取一些数据。

查询工作正常,但我无法弄清如何访问结果。我将它们全部存储在一个数组中,然后将该数组传递给一个函数。在控制台中,它们看起来像这样:

RowDataPacket {user_id: 101, ActionsPerformed: 20}
RowDataPacket {user_id: 102, ActionsPerformed: 110}
RowDataPacket {user_id: 104, ActionsPerformed: 3}

这里是查询结构:

var ret = [];
conn.query(SQLquery, function(err, rows, fields) {
    if (err)
        alert("...");
    else {
        for (var i of rows) 
            ret.push(i);
    }
    doStuffwithTheResult(ret);
}

doStuffwithTheResult 函数中,我如何检索这个值?值更重要一些,但如果能够获取键也是很好的。

17个回答

130

原来它们是普通对象,您可以通过user_id访问它们。

RowDataPacket实际上是创建对象的构造函数名称,它看起来像这样new RowDataPacket(user_id, ...)。您可以通过访问其名称[0].constructor.name进行检查。

如果结果是一个数组,则必须使用[0].user_id


1
感谢您回来回答自己的问题。我正在使用RowDataPacket.user_id,但它是未定义的。这节省了我一些麻烦 :) - Damodar Bashyal
4
如果结果以数组形式展示,那么您需要通过results[0].user_id来访问它们。 - zegulas
我有一个紧急问题,console.log如何记录非统一的JavaScript对象?底层发生了什么? - Ayyash

40

使用Object.prototype方法,JSON.parse(JSON.stringify(rows))返回一个对象,可使用Object.values()提取值。

let result = Object.values(JSON.parse(JSON.stringify(rows)));

用法:

result.forEach((v) => console.log(v));

如果您正在使用Babel / polyfill,则可能需要使用structuredClone:https://developer.mozilla.org/en-US/docs/Web/API/structuredClone - Max
超级解决方案!谢谢!仍然有效。 - Serhii Zelenchuk

31

最近我在使用Express项目中的Waterline进行复杂查询时遇到了同样的问题,需要使用SQL语句进行查询。

我的解决方案是:先将返回值(RowDataPacket对象)转换为字符串,然后将该字符串转换为JSON对象。

以下是代码:

//select all user (查询全部用户)
find: function(req, res, next){
    console.log("i am in user find list");
    var sql="select * from tb_user";

    req.models.tb_user.query(sql,function(err, results) {
        console.log('>> results: ', results );
        var string=JSON.stringify(results);
        console.log('>> string: ', string );
        var json =  JSON.parse(string);
        console.log('>> json: ', json);
        console.log('>> user.name: ', json[0].name);
        req.list = json;
        next();
    });
}

以下是控制台内容:

    >> results:  [ RowDataPacket {
    user_id: '2fc48bd0-a62c-11e5-9a32-a31e4e4cd6a5',
    name: 'wuwanyu',
    psw: '123',
    school: 'Northeastern university',                                                                                                                                           
    major: 'Communication engineering',                                                                                                                                            
    points: '10',
    datems: '1450514441486',
    createdAt: Sat Dec 19 2015 16:42:31 GMT+0800 (中国标准时间),                                                                                                  
    updatedAt: Sat Dec 19 2015 16:42:31 GMT+0800 (中国标准时间),                                                                                                  
    ID: 3,
    phone: 2147483647 } ]
>> string:  [{"user_id":"2fc48bd0-a62c-11e5-9a32-a31e4e4cd6a5","name":"wuwanyu","psw":"123","school":"Northeastern university","major":"Communication engineering","points":"10","datems":"1450514
441486","createdAt":"2015-12-19T08:42:31.000Z","updatedAt":"2015-12-19T08:42:31.000Z","ID":3,"phone":2147483647}]
>> json:  [ { user_id: '2fc48bd0-a62c-11e5-9a32-a31e4e4cd6a5',
    name: 'wuwanyu',
    psw: '123',
    school: 'Northeastern university',                                                                                                                                           
    major: 'Communication engineering',                                                                                                                                            
    points: '10',
    datems: '1450514441486',
    createdAt: '2015-12-19T08:42:31.000Z',
    updatedAt: '2015-12-19T08:42:31.000Z',
    ID: 3,
    phone: 2147483647 } ]
>> user.name:  wuwanyu

11
我使用了JSON.parse(JSON.stringify(results)) - RozzA
我想在我的前端页面上显示结果,而我所要做的就是 res.send(JSON.stringify(results)),不需要使用 JSON.parse。它会自动在前端进行解析。感谢您指引我正确的方向! - Noam Hacker
注意:在大多数情况下,评论中RozzA的答案都能解决问题,感谢RozzA。 - WebDev-SysAdmin
对于那些考虑使用JSON.parse/JSON.stringify的人:如果您正在使用Babel/填充程序,则使用structuredClone可能是相关的:https://developer.mozilla.org/en-US/docs/Web/API/structuredClone - Max

20

嗨,试试这个方法,百分百有效:

results=JSON.parse(JSON.stringify(results))
doStuffwithTheResult(results); 

如果您正在使用Babel / polyfill,则可能需要使用structuredClone:https://developer.mozilla.org/en-US/docs/Web/API/structuredClone - Max
需要查看是否会影响日期时间对象,但目前字符串、整数和浮点数都没有问题。 - WEBjuju

15

您可以通过Object.assign(target, ...sources)将一个对象的所有可枚举自有属性复制到一个新对象中:

trivial_object = Object.assign({}, non_trivial_object);
在您的情况下,只需要更改即可。
ret.push(i);

ret.push(Object.assign({}, i));

这绝对比JSON.parse(JSON.stringify(x))更加简洁,但我不知道性能差异是什么... - Dave Gregory
2
请记住,这只是浅层复制,深层属性可能仍然是引用。 - plumpNation
相关链接:https://web.dev/structured-clone/ - Max
或者只需使用解构 ret.push( { ...i } ) - vess

6

您可以尝试以下代码,它能够输出无rowdatapacket的JSON:

var ret = [];
conn.query(SQLquery, function(err, rows, fields) {
    if (err)
        alert("...");
    else {
        ret = JSON.stringify(rows);
    }
    doStuffwithTheResult(ret);
}

2
当我执行ret[0]时,我只得到了"["而不是整行? - Wayneio
1
@Wayneio 这是因为ret是一个JSON字符串,而ret[0]返回的是它的第一个字符,即[ - tuomassalo

4
基于Jan的浅拷贝对象的答案,另一种干净的实现方法是使用map函数。
该解决方案的高级别操作:遍历所有行并将这些行复制为有效的JS对象。
// function  will be used on every row returned by the query
const objectifyRawPacket = row => ({...row});

// iterate over all items and convert the raw packet row -> js object
const convertedResponse = results.map(objectifyRawPacket);

我们利用了数组映射函数:它将遍历数组中的每个项,将项用作函数的输入,并将函数的输出插入到您正在分配的数组中。
更具体地说,在objectifyRawPacket函数中:每次调用该函数时,它都会从源数组中看到“{RawDataPacket}”。这些对象的行为很像普通对象-“...”(展开)运算符将期间后面的项目从数组中复制-实质上将项目复制到被调用的对象中。
函数周围的圆括号是必需的,以便从箭头函数中隐式返回一个对象。

3
我尝试了你的解决方案,与将JSON转为字符串再解析相比(多次比较不同数量和长度的记录),它的速度更快。 我使用for loop代替map来尝试,速度略有提升。 在所有方法中,Object.assign()是最快的(jan的解决方案)。 比较结果:https://gist.github.com/jastisriradheshyam/3e69aeda1b169345e3834b7b8f891560#gistcomment-3049253 - Jasti Sri Radhe Shyam

4

解决方案

只需执行:JSON.stringify(results)


3
我找到了一种简单的方法。
Object.prototype.parseSqlResult = function () {
    return JSON.parse(JSON.stringify(this[0]))
}

在数据库层面进行解析,步骤如下:

let users= await util.knex.raw('select * from user')
    return users.parseSqlResult()

这将会返回一个普通的JSON数组元素。

3

如果有人需要从多个查询中检索特定的RowDataPacket对象,这里是方法。

开始之前

重要: 确保在mysql连接中启用multipleStatements如下:

// Connection to MySQL
var db = mysql.createConnection({
  host:     'localhost',
  user:     'root',
  password: '123',
  database: 'TEST',
  multipleStatements: true
});

多查询

假设我们有多个查询正在运行:

  // All Queries are here
  const lastCheckedQuery = `
    -- Query 1
    SELECT * FROM table1
    ;

    -- Query 2
    SELECT * FROM table2;
    `
    ;

  // Run the query
  db.query(lastCheckedQuery, (error, result) => {
    if(error) {
      // Show error
      return res.status(500).send("Unexpected database error");
    }

如果我们使用console.log(result),你将会得到以下输出结果:
[
  [
    RowDataPacket {
      id: 1,
      ColumnFromTable1: 'a',
    }
  ],
  [
    RowDataPacket {
      id: 1,
      ColumnFromTable2: 'b',
    }
  ]
]

两个表格都显示了结果。

这里是基本的JavaScript数组发挥作用的地方:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

要从 table1 和名为 ColumnFromTable1 的列中获取数据,可以执行以下操作:

result[0][0].ColumnFromTable1 // Notice the double [0]

这给我们提供了a的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接