2

node-csv-parserを使用してcsvデータを読み込み、mongooseを使用してmongodbに保存しています。node-mongodb-nativeただし、インポートを高速化しようとしているので、を使用してマングースでアクセスされる、によって公開されたネイティブの保存メソッドを使用して評価したいと思いますModel.collection。(これは、モンゴ本社の営業時間に話したモンゴエンジニアのアドバイスによるものです)。

node-csv-parserdatacsvの新しい行を読み取るたびにイベントを発生させます。このイベント内で、データの行を読み取り、そこから新しいデータポイントを作成し、mongoに保存します。dataマングースモデルを使用して、イベント内にデータポイントを適切に保存できますTestDataPoint。ただし、代わりにデータポイントのjavascriptオブジェクトを作成し、を使用して保存しようとするとTestDataPoint.collection.save、次のエラーが発生しますRangeError: Maximum call stack size exceeded

コレクションを直接取得したり、非同期モジュールmongoose.connection.db.collection("testdatapoints")によって提供されるキューに送信したりするなど、さまざまな方法でこのネイティブ保存を呼び出してみましたが、結果はほぼ同じです。コードの他の場所でネイティブドライバーを使用してデータポイントを正常に保存できます。また、イベント内ではなく、csvインポートのイベント内でも正常に保存できます。enddata

また、ログを記録することで、現在のセットアップ(64ビットAMDプロセッサのUbuntu 12.04、8 GB RAM)で、コードがスタックエラーをスローする前にcsvの154行を繰り返すことを確認しましたが、データはデータベースに書き込まれませんこのdataイベントの中から。意図せずに何らかの再帰が発生しているようです(?)、またはnode-csv-parserとnode-mongodb-nativeの間のある種のバグである可能性があります。

明確にするために、以下の私の(編集/更新された)サンプルコードを使用すると、ログは154回繰り返されます。

about to call native save
just called native save

そして言う:

in native save callback for dataPoint: 1
Native save failed, error:RangeError: Maximum call stack size exceeded
in native save callback for dataPoint: 2
Native save failed, error:RangeError: Maximum call stack size exceeded

dataPoint 154までは、「もうすぐ呼び出す/呼び出されたばかり」をさらに154回繰り返し、dataPoints 155-308などのエラーをログに記録します(インポートするデータポイントがたくさんあります)。この154の数字はかなり再現性があり、一度に155行を1〜2回通過するのを観察したと思います。

process.nextTick()スタックをクリアするために、save呼び出しをでラップすることが提案されました。これを試してみると、ログで、保存が154回呼び出され、次にprocess.nextTick()154回呼び出され、次にRangeErrorが154回ログに記録され、シーケンスが繰り返されることがわかります。

ノード0.8.2、mongoose 2.7.2、mongodb2.0.4を実行しています。

csv()
    .fromPath(path)
    .on("data", (data, index) ->

        # cellTest is an instance of a Mongoose model object
        newDataPoint = 
            testId: cellTest.testId    # this assignment was causing recursion in the native save
            dataPoint: data[1]
            testTime: data[2]/3600
            cycleIndex: data[3]

        console.log "about to call native save"

        # TestDataPoint is my my mongoose model, which saves fine, but
        # this call throws the RangeError: Maximum stack size exceeded
        TestDataPoint.collection.save newDataPoint, safe:true, (err, dataPoint) ->
            console.log "in native save callback for dataPoint: " + data[1]
            if err
                console.log "Native save failed, error:" + err

        console.log "just called native save"

    .on("end", (count) ->
        newDataPoint = 
            dataPoint: 100            # dummy values
            testTime: 200
            cycleIndex: 300

        # This call works, saves the data point
        TestDataPoint.collection.save newDataPoint, safe:false, null
    )
    .on("error", (err) ->
       console.log err
    )

編集:解決しました!

割り当て:

testId: cellTest.testId

保存時に再帰を引き起こしていました。別のマングースモデルのインスタンスであるcellTestと関係があります。割り当てを次のように変更します。

testId: parseInt(cellTest.testId)

再帰を排除し、保存を実行できるようにしました。

4

1 に答える 1

1

この問題は解決されました。私の実際のコードでは、プロパティの 1 つをnewDataPoint別の Mongoose モデル オブジェクトの整数プロパティに設定しました。(次回は、サンプルからその詳細を「単純化」しないことを知っています!)これは、保存時に何らかの形で再帰を引き起こしていました。

parseInt()その値の割り当てをa で囲むことで修正しました。保存は正常に機能し、Mongoose を使用するよりも約 3 倍高速です (Mongoose を使用しないことでいくつかのことをあきらめていることはわかっていますが、単一のポイントがすべてではない多くのデータ ポイントをログに記録しているアプリケーションでは問題ありません)。それは重要です)。

于 2012-07-20T18:50:52.507 に答える