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

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

ただいまの
回答率

87.78%

【node.js】for文と変数を使って、mysql文を表現したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 425

score 19

やりたいこと

現在、node.jsで簡単なSNSアプリケーションを開発しており、ユーザーが過去に押した「いいね」のツイートを表示するということをやりたいです。そのために、mysqlでユーザーが過去に押した「いいね」のツイートのIDをDBから取得しようとしています。下の「ためしたこと」でも書いてありますが、sql文を表現しきっているはずなのになぜかうまくいかないです。

エラー文

Cannot read property 'forEach' of undefined
    at eval (C:\xampp\htdocs\sns_app\views\favorite.ejs:18:15)
    at favorite (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:691:17)
    at tryHandleCache (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:272:36)
    at View.exports.renderFile [as engine] (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:489:10)
    at View.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\view.js:135:8)
    at tryRender (C:\xampp\htdocs\sns_app\node_modules\express\lib\application.js:640:10)
    at Function.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\response.js:1012:7)
    at Query.connection.query (C:\xampp\htdocs\sns_app\app.js:131:17)
    at Query.<anonymous> (C:\xampp\htdocs\sns_app\node_modules\mysql\lib\Connection.js:526:10)

実装中のコード

app.get('/favorite', (req, res) => {
    var mysql1 = 'SELECT tweet_id FROM favorite WHERE user_id = ?';
    var mysql2 = 'SELECT * FROM tweets WHERE id = ';
    var mysql3 = 'SELECT * FROM tweets WHERE id = 4 OR id = 3';

    connection.query(
    mysql1,
    [user_id],
    (error,results)=>{
        for (var i = 1, len = results.length; i < len; ++i) {
            mysql2 = mysql2 + results[0].tweet_id + ' OR id = ' + results[i].tweet_id;
        }
        console.log('mysql2>>',mysql2);
        console.log('mysql3>>',mysql3);
    });

    connection.query(
        mysql2,
        (error,results)=>{
            console.log('favorite>>',results);
            res.render('favorite.ejs',{user:username,tweets:results,title:"お気に入り"});   
    });
});//app.favorite

実装中のコード 

<h3><%= title %></h3>
        <a href="/new_tweet">新規追加</a>
        <ul>
            <% tweets.forEach((tweet) => { %>
            <li class="tweet">
              <span class="tweet_content"><%= tweet.content %></span>
                  <% 
                    var category;
                    var list =["恋愛","科学","仕事","日常","広告","PC","病院","漫画","映画","ゲーム","政治"];
                    category = list[tweet.category];
                  %>
              <span class="category">#<%= category %></span>
              <a href="#" class="good_btn"><%= tweet.good %></a>
            </li>
          <% }); %>
        </ul>

ためしたこと

sql文がうまく表現できていないのかと思い、console.logに出力させたところ以下のようになりました。

mysql2>> SELECT * FROM tweets WHERE id = 4 OR id = 3
mysql3>> SELECT * FROM tweets WHERE id = 4 OR id = 3
favorite>> undefined

mysql3となっているのは試しでベタ打ちで書いてみたものです。ちなみに、mysql3をqueryの中に入れると、ちゃんと作動します。

バージョン

"dependencies": {
"ejs": "^3.1.5",
"express": "^4.17.1",
"jquery": "^3.5.1",
"mysql": "^2.18.1"
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • shibachi

    2020/10/14 00:32

    @attakei
    エラーの内容はER_EMPTY_QUERY: Query was emptyとなっていますね...

    キャンセル

  • shibachi

    2020/10/14 00:40

    @firegrape
    sql文を変数を使わないで、ベタ打ちをすると問題なく処理が走るのでresultsに値は入っているかと思います!

    キャンセル

  • attakei

    2020/10/14 01:53

    > エラーの内容はER_EMPTY_QUERY: Query was emptyとなっていますね...

    回答の方にも少し書いたんですが、これだと「クエリーが空」となっているために起きているようにも見えます。
    2度目のconnection.queryの中で定義されているコールバック関数内だと、mysql2はどういう内容になっているかを確認するとどうなるでしょうか?
    ※console.log('favorite>>',results);のタイミングでresultsではなくmysql2を表示させてみた場合

    キャンセル

回答 1

checkベストアンサー

0

※簡単に動作を手元で見返して、わかる範囲での回答にはなります

対処としての回答

クエリの結果から更にクエリを組み立てるのであれば、コールバック関数内でconnection.queryを実行したほうが良いと思います。

app.get('/favorite', (req, res) => {
    var mysql1 = 'SELECT tweet_id FROM favorite WHERE user_id = ?';
    var mysql2 = 'SELECT * FROM tweets WHERE id = ';
    var mysql3 = 'SELECT * FROM tweets WHERE id = 4 OR id = 3';

    connection.query(
    mysql1,
    [user_id],
    (error,results)=>{
        for (var i = 1, len = results.length; i < len; ++i) {
            mysql2 = mysql2 + results[0].tweet_id + ' OR id = ' + results[i].tweet_id;
        }
        console.log('mysql2>>',mysql2);
        console.log('mysql3>>',mysql3);
+        connection.query(
+            mysql2,
+            (error,results)=>{
+                if (error) throw error; // SQLエラー時の検知用
+                console.log('favorite>>',results);
+                res.render('favorite.ejs',{user:username,tweets:results,title:"お気に入り"});   
+        });
    });

-    connection.query(
-        mysql2,
-        (error,results)=>{
-            console.log('favorite>>',results);
-            res.render('favorite.ejs',{user:username,tweets:results,title:"お気に入り"});   
-    });
});//app.favorite

※エラーのキャッチアップ目的で、if (error) throw error;を挿入しています。
resultsundefinedになっている理由を探すという意味でも、
エラーが無いことが確認できる流れで通常処理に進んだほうが良いかと。

原因(仮説を含む

Node.jsのコールバック関数の処理が非同期で動きます。
そのため、最初のconnection.queryでメインのクエリ処理がされたあと、
指定したコールバック関数と2回目のconnection.queryのクエリ処理の
どちらが先に処理されるかがわかりません。

そのため、上記のようにコールバック内で処理をつなぐようにするか、
async/awaitなどのように処理順序をある程度担保出来る実装が必要になります。

※ここから先、自環境で不明瞭だった点

変数mysql2は当然ながら後続で組み立てることを前提にしているため、
初期段階ではSQLとしての構文は誤っています。(これ自体は正常)
そのため、近い環境を手元で用意して簡易的に試した範囲ではerrorの内容が、
構文エラーであるER_PARSE_ERRORとなっていました。

ただ、修正依頼欄で確認してもらったエラーはER_EMPTY_QUERYという、
空文字列でクエリ実行した時に出るエラーだったので、
そこの齟齬が起きた理由だけはちょっとわかっていません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/14 17:22

    返信遅くなり申し訳ないです!
    たったいま確認したところ、きちんと表示されました!!
    console.log();の出力結果を見て、内容がおかしかったのでそこだけ修正しました。↓

    --------------------------------------------------------------------------------------
    app.get('/favorite', (req, res) => {
    var mysql1 = 'SELECT tweet_id FROM favorite WHERE user_id = ?';
    var mysql2 = 'SELECT * FROM tweets WHERE id = ';

    connection.query(
    mysql1,
    [user_id],
    (error,results)=>{
    if (error) throw error;
    console.log('user_id',user_id);
    console.log('results_id',results);
    mysql2 = mysql2 + results[0].tweet_id;
    for (var i = 1, len = results.length; i < len; ++i) {
    mysql2 = mysql2 + ' OR id = ' + results[i].tweet_id;
    }//for
    console.log('mysql2>>',mysql2);
    connection.query(
    mysql2,
    (error,results)=>{
    if (error) throw error; // SQLエラー時の検知用
    console.log('favorite>>',results);
    res.render('favorite.ejs',{user:username,tweets:results,title:"お気に入り"});
    }
    );
    }
    );
    });//app.favorite

    キャンセル

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

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る