Wordpress REST API、Node.js + Express + EJS、MongoDBを使い複数サイトを一本化するPart1

Wordpress REST API、Node.js + Express + EJS、MongoDBを使い複数サイトを一本化する
少し前に「Node.js+Express+EJSとWordPress REST APIでViewを再構築する実験」と「WordPress REST APIで得たJSONをNode.jsとMongoDBを使い保存する」を掲載したので、今回はこれらの複合技。昨今、キュレーションサイトが問題になっているが、それどころではなく、複数のWordPressサイトをまるまるパクリ(笑)、一本化するサイトの構築方法となる。

この時肝になるのが、”APIを使って複数サイトのデータをMongoDBへ保存する方法”と、”post、categories、tagsのIDが被る可能性があるので、それを回避する方法”だ。まずPart1では前者から説明したい。

サイトのソースは、自分のブログと、許可を得て、http://techtalk.pcmatic.jpのブログ、この2つを使っているが(画面キャプチャ上のタイトルがtechtalk.pcmatic.jp、下のタイトルがblog.iwh12.jp)、ロジック上はいくつでも対応可能となっている。

単一サイトからAPIを使いMongoDBにpost、categories、tagsのcollectionを保存するのはもう説明済だが、複数サイトを対象とした非同期での書き込みは、全て完全に終了したのを知るにはいろいろ面倒なことになる。

そこで今回はasync(npm install async)モジュールを使うことにした。使い方は以下の通り。

上から順にAPIが実行され、callbackが呼ばれるまでは次の処理に進まず、見かけ上、同期で作動する。

SetCollectionの4番目の引数はcollectionをdropするかどうか。以前説明したように、DBは差分ではなく、全件保存しなおしているため、2つめ以降のサイトはdropしないようにする。

そしてAPIを処理する側は、http.getのend部分を一部書き換える。追加したのはcallback()。これで一つのAPI呼出しとDBへの保存が終わったことを先のcallbackで知らせ、次の処理へ進むことが出来る。

以上で理論上はOKなのだが、実際はAPIを使ったデータの取得が(場合によっては)分単位になるため、DB書き換え中にサイトをアクセスすると、対象となるデータが不完全でエラーとなる。

これを回避するには、同じ構造の同期用DBと表示用DB、2つ持ち、APIでの同期が済み次第、表示用DBへ同期用DBをまるごとコピーするのが手っ取り早い。コードは以下の通り。

これはmongoコンソールで、db.copyDatabase(“wp0″,”wp”)とするのと同じ動きとなる。先のAPIでの読み込みをwp0へ行った後、console.log(‘Series all done.’);の後ろにあるこのプログラムでwpへまるまるコピーする。これなら瞬時なので、表示側に影響が出ることは(完全に無いとは言い切れないものの)無いだろう。

但し、表示側(ここではwp)のcollection 3つを先にdropしてからコピーする必要がある。

作動中のサイトはこちら。サイドバーのウィジェットは全てExpressでルーティングしたAPIを使って描画している(Part2で説明予定)。