2017-02-01 6 views
0

私は比較的NoSQLですが、私は非常に楽しんでいます!私はしかし、地図を減らす方法を見つけるのは少し難しいです!私は問題の助けが必要です!CouchDBはペア文書を検索し、残りのペアのない文書を一覧表示します

私は、オープントランザクションとクローズトランザクションという2種類のドキュメントを持つデータベースを持っています。レプリケーションとオフライン機能のために、を1つのドキュメントにマージできません。オープニングトランザクション文書は次のようになります。

終値取引の randomgeneratedstring
{ 
    _id: "transaction-close-randomgeneratedstring", 
    type: "transactions-close", 
    openid: "transaction-open-randomgeneratedstring", 
    created: "date string"  
} 

は、対応する開口トランザクションのrandomgeneratedstringと一致:

{ 
    _id: "transaction-open-randomgeneratedstring", 
    type: "transactions-open", 
    vehicle: "vehicle-id", 
    created: "date string" 
} 

決算書類をようになります。

私は私に対応するクロージングトランザクションを持っていない開いているトランザクションのリストを与えるためにマップが-減らす必要があります。これは、基本的に私に未払いの取引のリストを与えます。

これは私がこれまで行ってきたマップリダクションですが、それは仕事をしていません。

{ 
    "map": function(doc) { 
    if(doc.type == "transactions-open") { 
     emit([doc._id, 0], "OPEN"); 
    } 
    if(doc.type == "transactions-close"){ 
     emit([doc.openid, 1], "CLOSE"); 
    } 
    }, 
    "reduce": function(keys, values, rereduce) { 
    var unique_labels = {}; 
    var open = {}; 
    keys.forEach(function(label) { 
    if(!unique_labels[label[0]]) { 
     unique_labels[label[0]] = true; 
    } else { 
     open[label[0]] = true; 
    } 
    }); 
    return open; 
    } 
} 

私は_idの命名/構造の変化のために開いていますが、私は一つに二つの文書を組み合わせることはできません。

ありがとうございます! 、これは確かに正しい方向への一歩ですが、不要なトランザクションは、結果セットに残っている

function(keys, values, rereducer) 
{ 
    if(values.length == 1) 
    return true; 
} 

EDIT はホッドからの応答に基づいて、私が見えるように削減を変更しました値はnullのみです。結果セットからそれらを取得する方法はありませんか?

答えて

0

説明したように、あなたはCouchDBでの削減とは何か、あなたはSQLで結合しますか?

{ 
    "map": function(doc) { 
    if(doc.type == "transactions-open") { 
     emit([doc._id], 1); 
    } 
    if(doc.type == "transactions-close"){ 
     emit([doc.openid], -1); 
    } 
    }, 
    "reduce": "_sum"; 
} 

だから我々は、IDの下に開いたトランザクションのための1を放出し、同じIDの下に近いため-1:テストされていません - このようなコードの何か。今度は、あなたが各IDの結果を得るでしょう:

  • -1 =開いている(エラー条件)のレコードなしで閉じます。
  • 0 =開いて閉じた
  • 1 =開いていて閉じていない。
0

問題は、あなたの軽減機能でkeysパラメータです。 reduceフェーズは、すべての可能なキーで一度呼び出されません。それは別個のキーと呼ばれ、あなたが指定するgroup_levelに基づいています。あなたはどんなgroup_levelを指定していない場合は

、あなたのコードを見てみると、あなたの軽減機能は、個別にすべての文書を呼びかけ取得する予定です。

あなたが最初のレベルでグループ化された場合は、開いたり、オープン/クローズのペアを取得したい、開閉両マーカーのためのオープン・トランザクションドキュメントのIDを放出しているため。一度に限定された一連のドキュメントを削減するだけです。

次のいずれかのクエリを呼び出すあなたのロジックで、またはあなたが一度セット全体に減らすのを聞かせてキーを発することによってこの問題を解決することができます。 (別の方法もあると思いますが)。

キーアプローチを使用する場合、["transaction", doc._id, 0]のようなものを放出する必要があります。そして、最初のレベルのグループ化は、現在のコードが期待しているようにトランザクション全体を設定します。

EDIT(質問の編集に基づいて情報を追加します。)

reduce関数は、あなたが設定したグループ化があれば呼び出されます。結果がまったく出力されない場合(つまりnullの場合)でも、常に何かが返されます。

クエリを実行して結果を処理するロジックでこれを処理したくない場合は、すべてのトランザクションドキュメントをまとめてグループ化できるアプローチを使用する必要があります。単一の取引。

あなたがこれまで行ってきたことに基づいて、もう一つのアプローチは、縮小段階を控えて、ユニークなドキュメントIDに限定されたクエリによって返された結果の数を調べることです。

+0

ありがとうございました!あなたはreduce関数の仕組みについて多くの光を放っています!私の地図では、openのdoc._idとclosedのdoc.openidは同じです。レベル1でグループ化すると、両方の取引が減額されますか?キーの長さが1より大きいインスタンスの場合、私がreduceで何も返さないとどうなりますか? – monkeyman

+0

はい、レベル1でグループ化すると、完了したトランザクションの2つのドキュメントを1回の短縮コールにバンドルする必要があります。何も返さないか、長さ0の配列が使えます。 – Hod

関連する問題