2016-05-11 4 views
0

Firebaseからデータをフェッチして返すAPI(私のサーバを指している)をユーザに提供したいと思います。私は、それがストリーミングではなく、「通常の」ポイントインタイムリクエストであることを望んでいます。ある時点でリスト内に複数のオブジェクトを取得する方法

私のデータは 'projects'内の 'boxes'です。ユーザーは自分のAPIに問い合わせてプロジェクトのすべてのボックスを取得できます。

私のデータは正規化されているので、プロジェクトを検索し、そのプロジェクトのボックスのキーのリストを取得し、各ボックスレコードを個別に取得します。一度それらをすべて持っていれば、私はユーザーにアレイを返すでしょう。

私の質問:これを行う最善の方法は何ですか?

これは私が持っているものであり、動作します。しかし、それはとてもハッキリです。

const projectId = req.params.projectId; // this is passed in by the user in their call to my server. 

    const boxes = []; 
    let totalBoxCount = 0; 
    let fetchedBoxCount = 0; 

    const projectBoxesRef = db 
    .child('data/projects') 
    .child(projectId) 
    .child('boxes'); // a list of box keys 

    function getBox(boxSnapshot) { 
    totalBoxCount++; 

    db 
     .child('data/boxes') // a list of box objects 
     .child(boxSnapshot.key()) 
     .once('value') 
     .then(boxSnapshot => { 
     boxes.push(boxSnapshot.val()); 

     fetchedBoxCount++; 

     if (fetchedBoxCount === totalBoxCount) { 
      res.json(boxes); // leap of faith that getBox() has been called for all boxes 
     } 
     }); 
    } 

    projectBoxesRef.on('child_added', getBox); 

    // 'value' fires after all initial 'child_added' things are done 
    projectBoxesRef.once('value',() => { 
    projectBoxesRef.off('child_added', getBox); 
    }); 

child_addedオブジェクトの初期セットを分離する上でいくつかの他の質問/回答はありますが、彼らは私の現在の意思決定に影響を与えたが、彼らは直接関連していないようです。

ありがとうございました。

アップデート:以下ジェイの答えのJavaScriptバージョン:

db 
    .child('data/boxes') 
    .orderByChild(`projects/${projectId}`) 
    .equalTo(true) 
    .once('value', boxSnapshot => { 
    const result = // some parsing of response 

    res.json(result); 
    }); 

答えて

1

これはあまりにも簡単な解決策かもしれませんが、あなたがプロジェクトを持っている場合、それぞれのプロジェクトがボックス

プロジェクトノード

projects 
    project_01 
    boxes 
     box_id_7: true 
     box_id_9: true 
     box_id_34: true 
    project_37 
    boxes 
     box_id_7: true 
     box_id_14: true 
     box_id_42: true 
を持っています

とボックスノード

boxes 
    box_id_7 
    name: "a 3D box" 
    shape: "Parallelepiped" 
    belongs_to_project 
     project_01: true 
    box_id_14 
    name: "I have unequal lenghts" 
    shape: "Rhumboid" 
    belongs_to_project 
     project_37: true 
    box_id_34 
    name: "Kinda like a box but with rectangles" 
    shape: "cuboid" 
    belongs_to_project 
     project_01: true 

これで、boxesノードの1つの(深い)クエリは、project_01に属するすべてのボックスをロードします。この場合、box_id_7とbox_id_34です。

あなたはプロジェクトノードの各プロジェクトのボックスIDを知っているので、一連のオブザーバーを使って各プロジェクトを特定のパス/ボックス/ボックス_id_7などで読み込むことができますより良いクエリ。高速かつ低帯域幅。ボックスは、複数のプロジェクトに所属することができます場合は、この上で展開することができ

box_id_14 
    name: "I have unequal lenghts" 
    shape: "Rhumboid" 
    belongs_to_project 
     project_01: true 
     project_37: true 

今すぐproject_01の一部であるすべてのボックスのボックスノードにクエリがbox_id_7、box_id_14とbox_id_34を取得します。

編集:

その構造一旦、問題のプロジェクトに属しているのボックスを取得するために、ディープクエリを使用し、所定の位置にあります。例えば

:あなたはボックスのbelongs_to_projectリストは、キーを持つ項目が含まれているすべてのボックスを返すためにFirebase Deep Queryを作るために必要があるとし、「project_37」

boxesRef.queryOrderedByChild("belongs_to_project/project_37" 
    .queryEqualToValue(true) 
    .observeSingleEventOfType(.Value, withBlock: { snapshot in 
     print(snapshot) 
}) 
+0

いいですね。でも、「1(深い)クエリ」はどのように見えますか? –

+0

@DavidGilbertsonディープクエリー[ディープクエリー](https://www.firebase.com/blog/2015-09-24-atomic-writes-and-more.html)について説明しているfirebaseウェブサイトの素晴らしいブログ記事があります。また、ここでは例のスタックオーバーフローについても検索します。あなたのプラットフォームが何であるか分かりませんし、ウェブサイト上の例も異なっています。私はMacOS SwiftやObj-Cを使っています。あなたがブログの投稿を見直した後に、あなたが何かを必要とするかどうかを教えてください。そのために – Jay

+0

ありがとうございます。私はちょうどその投稿と他の '深いクエリ'の質問を読んだが、私はまだこれを行うために深いクエリを使用する方法を見ることができません(ボックスには、彼らが属するプロジェクトへの参照はありませんそれはあなたが何を考えていたのか?)。私はJavaScript SDKを使用しています。 –

0

OK私が使用して、私は私のアプローチに満足だと思います

約束を使用する方法を変更してから、すべてのデータを送信する準備が整ったことを示すためにPromise.all()を呼び出してください。

const projectId = req.params.projectId; 

const boxPromises = []; 

const projectBoxesRef = db 
    .child('data/projects') 
    .child(projectId) 
    .child('boxes'); 

function getBox(boxSnapshot) { 
    boxPromises.push(db 
    .child('data/boxes') 
    .child(boxSnapshot.key()) 
    .once('value') 
    .then(boxSnapshot => boxSnapshot.val()) 
); 
} 

projectBoxesRef.on('child_added', getBox); 

projectBoxesRef.once('value',() => { 
    projectBoxesRef.off('child_added', getBox); 

    Promise.all(boxPromises).then(boxes => res.json(boxes)); 
}); 
関連する問題