質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

解決済

2回答

1952閲覧

nodejsでmysql2

Sosupe1123

総合スコア66

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

0グッド

0クリップ

投稿2022/10/06 13:19

編集2022/10/06 13:34

実現したいこと

nodejsでmysql2を使っていて以下のクエリを実行したときに返ってくるものの処理の仕方が知りたいです。この変数の型がなんなのかいまいちつかめてないです。

該当のソースコード

js

1const [row1] = await connection.query(`select count(*) from accounts where email = '${req.body.email}'`); 2console.log(row1);

試したこと

とりあえず返ってくるデータを表示させてみたいんですがこうなりました。この中の数字だけを取得したいです。

[ { 'count(*)': 0 } ]
console.log(row1["count(*)"]);

も当然エラーでダメでした。

補足情報(FW/ツールのバージョンなど)

mysql2@2.3.3
nodejs@18.10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Sosupe1123

2022/10/06 13:55

配列のように見えたので表示させましたがだめでした。うまくいかなかったのでこうして質問をしたのですが。
maisumakun

2022/10/06 14:03

> 当然エラーでダメでした。 どのようなエラーが出たのですか?
Sosupe1123

2022/10/06 14:05

``` TSError: ⨯ Unable to compile TypeScript: index.ts:49:22 - error TS7053: Element implicitly has an 'any' type because expression of type '"count(*)"' can't be used to index type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader'. Property 'count(*)' does not exist on type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader'. 49 logger.debug(row1["count(*)"]); ``` です。予想していた型とはそもそもが違っていたのでよくわからないです
hoshi-takanori

2022/10/06 21:18

row1 はオブジェクトの配列なので、row1[0]["count(*)"] かなぁ。
Sosupe1123

2022/10/06 22:30

``` ^ TSError: ⨯ Unable to compile TypeScript: index.ts:49:22 - error TS7053: Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader'. Property '0' does not exist on type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[] | ResultSetHeader'. 49 logger.debug(row1[0]["count(*)"]); ~~~~~~~ at createTSError (/app/api/node_modules/ts-node/src/index.ts:859:12) at reportTSError (/app/api/node_modules/ts-node/src/index.ts:863:19) at getOutput (/app/api/node_modules/ts-node/src/index.ts:1077:36) at Object.compile (/app/api/node_modules/ts-node/src/index.ts:1433:41) at Module.m._compile (/app/api/node_modules/ts-node/src/index.ts:1617:30) at Module._extensions..js (node:internal/modules/cjs/loader:1203:10) at Object.require.extensions.<computed> [as .ts] (/app/api/node_modules/ts-node/src/index.ts:1621:12) at Module.load (node:internal/modules/cjs/loader:1027:32) at Function.Module._load (node:internal/modules/cjs/loader:868:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) { diagnosticCodes: [ 7053 ] } ``` そもそも動かせてくれません。なんの型なのかがよくわからない....
maisumakun

2022/10/06 22:37

> なんの型なのかがよくわからない.... とりあえず(row1 as any)として、型チェックを殺してみてはどうでしょうか。
Sosupe1123

2022/10/06 23:03

[row1]: any としたら行けました。ありがとうございます
guest

回答2

0

ベストアンサー

公式ドキュメント読め案件です。
参考サイト: github.com/sidorares/node-mysql2

……だけで投げっぱなしにされると辛いと思うので、
私と一緒に読み解いていきましょう。


js

1const [row1] = await connection.query(`select count(*) from accounts where email = '${req.body.email}'`);

質問文では返り値を受け取って展開する箇所をrow1という名称で宣言して
あたかも汎用オブジェクト(PHP等でいう連想配列)みたいな取り扱いをしています。

connection.queryconnection.executeawaitで受け取った結果は、
0番目の要素がrows、1番目の要素がfieldsの配列です。

Using Promise Wrapperのサンプルコード

js

1const [rows, fields] = await connection.execute('SELECT * FROM `table` WHERE `name` = ? AND `age` > ?', ['Morty', 14]);

ダイレクトにrowsの結果が帰ってくるから[row1]で1行目にアクセス出来る前提のコードになっているのが勘違いなわけですが、
こういう書き方を指示した記事や教材なんかがあるかもしれないですね。

ライブラリ作った人間が用意しているドキュメントが一番正解に間違いなくて
Qiitaや個人ブログの記事や教材等は嘘が書いてある、もしくはバージョンが古くてそのうち嘘になるので、
参考元のリンクが無いようなものは鵜呑みにしないよう注意してください。


この変数の型がなんなのかいまいちつかめてないです。

row1はオブジェクトの配列です。
質問文のコードは配列の1要素目ではなく、[rows, fields]の配列からrowsを抜き出してるだけなので。

因みにrow1は配列ですが、
0番目の要素はオブジェクトが入っているはずです。
型表記Array<object>とかになりそうです。

Array resultsによるとこのような記述があります。

{ sql: 'select 1 as foo, 2 as foo', rowsAsArray: true }
will be an array of arrays rather than an array of objects

意訳: rowsAsArray: trueを指定した場合、rowsは「オブジェクトの配列」ではなく「配列の配列」を返すようになります。
要するにオプションを指定しない場合、「オブジェクトの配列」を返すと明示しているわけですね。


質問文から修正して
動くコードにするとこんな感じ

js

1const [[row]] = await connection.query(`select count(*) as account_num from accounts where email = ?`, [req.body.email]); 2console.log(row.account_num);

以下修正内容です。

  • 分割代入は二重配列にも対応しているので、[[row]]としてrows[0]を引っ張り出した
  • count(*)キーはやばいので、引っ張ったアカウントの個数という点に着目してas account_numという風に列別名を指定した
  • SQLインジェクション脆弱性に対処する為に?を利用してmysql2流儀の値の注入を行った

投稿2022/10/07 08:14

編集2022/10/07 08:27
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

[row1]:any..... console.log(row1[0]["count(*)"]);

無理やり型をanyにしたら行けた

投稿2022/10/06 23:03

Sosupe1123

総合スコア66

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問