カテゴリー : 2015年 10月

[Mongoose] index が未作成な field を sort に指定して stream で取得すると default batchSize だけ処理して正常終了するので困った

Mongoose で index が作成されていない field を sort に指定して stream で取得すると、 default batchSize の 1000 件だけ処理して正常終了するので困ったというお話です。

find() で全件一括取得するケース

find() で全件一括取得すると callback の第一引数 err には値は入らず、配列の末尾の要素に $err, code が含まれていました。

User.find().sort({
  createdAt: -1
}).setOptions({
  noCursorTimeout: true
}).exec(function(err, docs) {
  console.log(err);
  console.log(docs.length);
  console.log(docs[docs.length - 1]);
 
/**
以下、console.log の出力結果
 
null
1001
{ '$err': 'getMore runner error: Overflow sort stage buffered data usage of 33555763 bytes exceeds internal limit of 33554432 bytes',
  code: 17406,
...
**/
});

stream() で全件取得するケース

stram() で取得する場合も同じで、最後に取得した document に $err, code が含まれていました。

var stream = User.find()
.sort({ createdAt: -1 })
.setOptions({ noCursorTimeout: true })
.stream();
 
stream.on('data', function(user){
/**
default batchSize 1000 件だけ取得して、1001 件目に $err, code を含むデータを取得して、正常終了する
{ '$err': 'getMore runner error: Overflow sort stage buffered data usage of 33555763 bytes exceeds internal limit of 33554432 bytes',
  code: 17406,
...
**/
});
 
stream.on('error', function(err){
  // エラーイベントは呼び出されない
});

解決方法

sort に指定する field の index を作成する

index が作成されていないのが元々の問題なので、index 作成すれば解決します。

User.path('createdAt').index(true);

index が存在する field を sort に指定する

index size が気になるので作成したくないという場合は、default で用意されている _id を sort に指定する対応でもいいと思います。

User.find().sort({
  _id: -1
}).setOptions({
  noCursorTimeout: true
}).exec(function(err, docs) {});

所感

document が 1000 件しか取得できてないことに気付かない限り、エラーが発生していることに気付けないので Mongoose のエラーハンドリングの実装が微妙なのでは…


参考情報

Node.js のバージョンを自動で切換えてくれる avn

Node.js のバージョンを自動で切換えてくれる npm モジュール avn を使ってみました。(最終更新日 2017/04/15)

avn, avn-nvm, avn-n をインストール&セットアップ

$ npm install -g avn avn-nvm avn-n
$ avn setup
avn: profile setup complete (~/.zshrc)
avn: profile setup complete (~/.bash_profile)
avn: restart your terminal to start using avn
avn: configuration complete (~/.avnrc)
avn: installation complete
avn-n: installation complete
avn-nvm: installation complete

avn で Node.js のバージョンを切換えてみる

.node-version ファイルが存在するディレクトリに移動すると avn が自動的に Node.js のバージョンを切換えてくれます。

.node-version のサンプル

v6.10.2
$ cd ~/works/my_project
avn activated v6.10.2 (avn-nvm v6.10.2)

nvm の元となる rvm だと自動的に Ruby のバージョンを切換えてくれていたので、それと同じような挙動をしてくれるようになるのは嬉しいですね。

中国の国名コード CN と C2 の違い #country_code

PayPal API ドキュメントの国コード を読むと、中国には CN と C2 という2つ記載されていたのでその違いについて調べてみました。

CHINA

  • CN (For domestic Chinese bank transactions only)
  • C2 (For CUP, bank card and cross-border transactions)

日本語に翻訳すると、中国国内と国外の決済で CN と C2 の国コードを使い分ける必要があるみたいでした。

  • CN (中国国内の Chinese bank での決済のみ)
  • C2 (CUP [China UnionPay] 銀行カード、かつ、海外取引)

C2 は PayPal が独自に定義している国コードで、一般的には中国の国コードは CN です。

海外向け EC サイトを開発するときに決済手段に PayPal を選択肢として使う場合は、下記のような方針で実装するといいんじゃないかなと思いました。

  • 配送国の選択肢には CN を使う
  • PayPal API を使う部分だけ CN を C2 に変換して API を呼び出す
  • 配送サービス (EMSShippo など) では CN を使う
  • その他のロジックも全て CN で扱う

PayPal 独自の C2 は PayPal API を使うときだけ出てくればいいので、その他は全て CN を使うのがシンプルですよね。こうしないと中国だけ国コード判定のために CN, C2 のどちらも定義してあげないといけなくて微妙な実装になってしまいそうです。


参考情報