web-dev-qa-db-ja.com

Firebaseの多対多の関係

Firebaseデータベースがあります。会社と請負業者がいます。請負業者は複数の会社で働くことができ、会社は複数の請負業者を持つことができます。これは単純な多対多の関係です。会社と請負業者に関する質問に答えられるようにしたい:

  1. 現在の請負業者である会社を考える。
  2. 請負業者に、どの会社が働いているかを考えてください。

Firebase内でデータを構造化するための代替手段は何ですか?

33
Rob Gorman

実際、自己回答はこれをモデル化する1つの方法です。これはおそらく、リレーショナルデータベースでこれをどのようにモデル化するかに最も直接対応するものです。

  • 請負業者
  • 企業
  • companyAndContractorsAssignment(多対多のコネクタテーブル)

別の方法は、4つのトップレベルノードを使用することです。

  • 請負業者
  • 企業
  • companyContractors
  • 請負業者

最後の2つのノードは次のようになります。

_companyContractors
    companyKey1
        contractorKey1: true
        contractorKey3: true
    companyKey2
        contractorKey2: true
contractorCompanies
    contractorKey1
        companyKey1: true
    contractorKey2
        companyKey2: true
    contractorKey3
        companyKey1: true
_

この双方向構造により、「会社の請負業者」と「請負業者の会社」の両方を検索できます。どちらもクエリである必要はありません。これは、特に請負業者や企業を追加する場合は、より高速になるはずです。

これがアプリに必要かどうかは、必要なユースケース、期待するデータサイズなどに依存します。

推奨読書 NoSQLデータモデリング および表示 SQL開発者向けFirebase 。この質問は #AskFirebase youtubeシリーズのエピソード でも取り上げられました。

更新(2017016)

誰かが ここにリンクする追加の質問 を投稿して、「請負業者」ノードと「企業」ノードから実際のアイテムを取得しました。 FirebaseにはSELECT * FROM table WHERE id IN (1,2,3)に相当するものがないため、一度に1つずつ取得する必要があります。ただし、要求は単一の接続を介してパイプライン化されるため、この操作は思ったほど遅くありません。詳細については、こちらをご覧ください。 単一のイベントを繰り返し監視する代わりにクエリを使用して、ソーシャルネットワークアプリの投稿の取得を高速化

25

さらなる調査の後、自分の質問に答えてみます。他の多くの投稿を確認しましたが、多対多の問題の1つの解決策は、Companyオブジェクト内にContractorKeysのリストを保存し、各Contractorオブジェクト内にCompanyKeysのリストを保存することです。以下に例を示します。

companies : {
  companyKey1 : {
    name : company1
    ...
    contractors : {
      contractorKey1 : true,   
      contractorKey3 : true
    }
  }
  companyKey2 : {
    name : company2
    ...
    contractors : {
      contractorKey2 : true,  
    } 
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
     companies : {
        companyKey1 : true
     }
   }
  contractorKey2 : {
     name : steve
     ...
     companies : {
        companyKey1 : true
     }

   }
  contractorKey3 : {
     name : jim
     ...
     companies : {
        companyKey2 : true
     }
   }
}

この組織は、前述の質問に答えられるという意味で「機能します」。しかし、このソリューションの欠点は、請負業者/会社の割り当てが変更されたときに維持する2つのリストがあることです。この情報を単一のリストで表現する方法があればもっといいでしょう。

より良い解決策を思いついたと思います。解決策は、companyAndContractorAssignmentと呼ばれる会社と請負業者に加えて、3番目のリストを作成することです。このリストの要素は、単一の請負業者と会社の間の関係を表します。その内容は、contractorKeyとcompanyKeyのフィールドのペアになります。その後、企業内の請負業者リストと請負業者内の企業リストを削除できます。この代替構造を以下に示します。会社オブジェクト内に請負業者リストがなく、請負業者オブジェクトを持つ会社リストがないことに注意してください。

companies : {
  companyKey1 : {
    name : company1
    ...
  }
  companyKey2 : {
    name : company2
    ...
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
  }
  contractorKey2 : {
     name : steve
     ...
  }
  contractorKey3 : {
     name : jim
     ...
  }
}
companyAndContractorsAssignment : {
  key1 : {
    contractorKey1 : true,
    companyKey1: true,
  }
  key2 : {
    contractorKey3 : true,
    companyKey1: true,
  }
  key3 : {
    contractorKey2 : true,
    companyKey2: true,
  }

この代替構造により、companyAndContractorsAssignmentでorderByChild/equalToクエリを使用して質問に回答し、請負業者のすべての会社または会社のすべての請負業者を見つけることができます。そして、現在、維持するリストは1つだけです。これが私の要件に最適なソリューションだと思います。

5
Rob Gorman