2016-10-27 9 views
0

私はElasticSearchでExpress.js/Node.jsアプリケーションを実行しています。同じインデックス内の複数のタイプの結果を表示しようとしています。私がここで行うことは、検索クエリを実行し、クエリの結果に基づいて2番目の検索クエリが実行されます。私はelasticsearchがnode.jsコンソールを観察することによってプレーヤーの結果を返すことがわかります。しかし、私の結果オブジェクト/配列には挿入されません。私は2つの検索と表示の結果を1つとして実行する必要があるので、私はエクスプレスミドルウェアを使用しています。express.jsルートでreqオブジェクトに複数の結果を挿入する

ルート/ index.js

function searchTeam(req, res, next){ 
    searchModuleTeams.searchTeams(req.body, function(data) { 
    req.teams = data; 
    next(); 
    }); 
} 

function searchPlayer(req, res, next){ 
    //req.players = []; 
    req.teams.forEach(function(team){ 
    req.body = {searchTerm:team._source.shortName}; 
    searchModulePlayers.searchPlayers(req.body, function(data){ 
     req.players.push(data); 
     console.log(req.players); 
    }); 
    }); 
    next(); 
} 

function renderResults(req, res){ 
    res.render('index',{ 
    title:'Search Teams and Players', 
    teams:req.teams, 
    players:req.players 
    }); 
} 

router.post('/search-tp',searchTeam, searchPlayer, renderResults); 

私はpost1post2を読み取ることによって、この解決策を考え出しました。私はチームアレイを表示することができます。しかし、選手の配列から何も来ていない。私はここで間違っています。あなたのsearchPlayer機能で

+1

は() '、next()は、検索結果を取得する前に呼び出されます。 – Aynolor

+0

@Aynolorはあなたの次が間違っていると言っています。 それ以外に、私はデータを収集するために複数のミドルウェアを使うのは良いアプローチだとは思わない。 [aycnc](https://github.com/caolan/async)ライブラリを試しましたか?このユースケースでは、 'waterfall'メソッドが当てはまります。 –

+0

@Aynolor、@ Talha:次はどこに置くべきですか?私は結果をレンダリングする前にsearchPlayerの呼び出しを終了したいと思っています。私は非同期を探します。 – akalanka

答えて

1

next()コールはあなたがsearchTeam()機能のためにした基本的にはまさに、searchPlayers()によって呼び出されるコールバックの内側に配置する必要があります。

function searchTeam(req, res, next){ 
    searchModuleTeams.searchTeams(req.body, function(data) { 
    req.teams = data; 
    next(); 
    }); 
} 

function searchPlayer(req, res, next){ 
    req.players = [];      <--- uncomment this... 
    req.teams.forEach(function(team){ 
    req.body = {searchTerm:team._source.shortName}; 
    searchModulePlayers.searchPlayers(req.body, function(data){ 
     req.players.push(data);   <--- ...otherwise this will fail 
     next();       <--- move next() here 
    }); 
    }); 
} 

function renderResults(req, res){ 
    res.render('index',{ 
    title:'Search Teams and Players', 
    teams:req.teams, 
    players:req.players 
    }); 
} 

router.post('/search-tp',searchTeam, searchPlayer, renderResults); 

そして

タルハガムアワンにより示唆されるように、あなたが好ましくミドルウェアでこれを行うべきではありませんが、 async oneのように、専用のライブラリを使用して(しかし、他のトンがあります)searchPlayer `で

import waterfall from 'async/waterfall'; 

function searchTeam(callback){ 
    searchModuleTeams.searchTeams(req.body, function(teams) { 
    callback(null, teams); 
    }); 
} 

function searchPlayer(teams, callback){ 
    let teamPlayers = []; 
    async.each(teams, function(team, teamCallback) { 
    let search = {searchTerm: team._source.shortName}; 
    searchModulePlayers.searchPlayers(search, function(players){ 
     teamPlayers.push(players); 
     teamCallback(); 
    }); 
    }, function(err) { 
    callback(err, teams, teamPlayers); 
    }); 
} 

function renderResults(req, res){ 
    async.waterfall([ 
    searchTeam, 
    searchPlayer 
    ], function (err, teams, players) { 
    res.render('index',{ 
     title:'Search Teams and Players', 
     teams: teams, 
     players: players 
    }); 
    }); 
} 

router.post('/search-tp', renderResults); 
+0

非常に説明的な答えをありがとう。私は両方を試しました。現在、searchTeamに検索パラメータを渡す方法がわからないので、現在はwaterfallライブラリが動作しません。とにかく、ループの中にnext()を置くことによって最初のオプションを考えると、私はrenderResultsのプレーヤー配列にアクセスするのに問題があります。プレイヤーは、各配列にプレーヤーオブジェクトが含まれている配列の配列であると考えられます。 1つのチームのみが利用可能な場合、チームアレイには1つのアイテムが含まれ、プレイヤーアレイにはチームのプレーヤーのセットが含まれます。複数のチームが返された場合、それらのチームを編成する必要があります。 – akalanka

+0

非同期に与えた関数を指定されたコンテキスト(つまり 'this' + params)で 'バインド'することは間違いありません。たとえば、 'async.waterfall([ searchTeam.bind(null、42)、 searchPlayer ]'チームID = 42の検索を実行する場合は – Val

+0

私はasync.waterfallを試すべきだと思います。しかし、私はそれがすでにrenderResultsに送られていると思います。ループの後の反復で新しいデータで結果をレンダリングする方法はありません。関数を適切に反復処理し、すべての結果をレンダリングする他の方法はありますか?jsの非同期性のためにここにこだわっています。 – akalanka

関連する問題