web-dev-qa-db-ja.com

Cloud Firestore:コレクションクエリ内でドキュメント参照を取得し、JSON値としてマップする方法

コメントのコレクションがあるとしましょう。すべてのコメントオブジェクトには、投稿したユーザーへの「doc ref」があります。すべての単一ユーザー参照の値を含むコメントのリストを返すクエリが必要なので、クエリはJsonコメントオブジェクトのNice形式を返します。

9
Mauricio Silva

同様の質問がここで尋ねられました Firestore Referenceデータ型とは何ですか? 、この答えに従ってあなたが尋ねていることを行うことは可能ではないと思います https:// stackoverflow .com/a/46570119/47345

すべての参照を自分でロードする必要があります。

const comments = []
firebase.firestore().collection('/comments').get().then(snapshot => {
  snapshot.docs.forEach(doc => {
    const comment = doc.data()
    comment.userRef.get().then(snap => {
      comment.user = snap.data()
      comments.Push(comment)
    })
  })
})

多くのコメントでは、これにより多くのオーバーヘッドが追加されます。サーバー側ですべての作業を行い、フォーマットされたJSONを返すCloudFunctionを作成できます。

しかし、彼らは将来これをサポートすることに取り組んでいるようです: https://stackoverflow.com/a/46614683/47345

12
user473453

各コメントにユーザーデータを複製することをお勧めします。コメントドキュメントにuserという名前のオブジェクトであるフィールドを作成し、コメントの表示に必要な最小限の情報を提供します。したがって、commentドキュメントは次のようになります。

{
  id: 'CEXwQAHpk61vC0ulSdZy',
  text: 'This is a comment',
  user: {
    id: 'd5O4jTsLZHXmD1VJXwoE,
    name: 'Charlie Martin',
    avatar: 'https://...'
  }
}

これで、コメントを表示するために必要なものがすべて揃いました。誰かがコメントの作成者をクリックした場合、IDを取得し、それを使用してコメント作成者の完全なプロファイルをロードできます。

リレーショナルデータベースでは、これらのシナリオを外部キーで処理するように構築されているため、データの複製は嫌われています。

ただし、firestoreなどのNoSQLデータベースでは、データの複製が実際に推奨されますクエリを簡素化し、ネットワーク経由で送信されるデータ量を削減します。

各コメントに対して完全なuserドキュメントをロードした場合、コメントを表示するために必要な情報よりもはるかに多くのユーザーに関する情報をロードすることになります。

3
Charlie Martin

これも私を悩ませました。私はユーティリティヘルパーを作成しました。これは、最初のレベルに自動的に入力できます。

ヘルパー

import { get, set } from 'lodash'

const getReference = async documentReference => {
  const res = await documentReference.get()
  const data = res.data()

  if (data && documentReference.id) {
    data.uid = documentReference.id
  }

  return data
}

const hydrate = async (document, paths = []) => Promise.all(
    paths.map(async path => {
      const documentReference = get(document, path)

      if (!documentReference || !documentReference.path) {
        return console.warn(
          `Error hydrating documentReference for path "${path}": Not found or invalid reference`
        )
      }

      const result = await getReference(documentReference)
      set(document, path, result)
    })
  )
}

export { hydrate }

使用例:

getUser = async uid => {
  return this.db
    .collection('users')
    .doc(uid)
    .get()
    .then(async documentSnapshot => {
      const data = documentSnapshot.data()
      await hydrate(data, ['company', 'someOtherNestedRef-2', 'someOtherNestedRef-1'])
      return data
    })
}

制限:この例は、深くネストされた参照では機能しません

0
ChrisRich

私はこのためのソリューションを作成します、少なくとも私のために働く!

ユーザーが2つのコレクションを持っていると想像してください:ユーザーと友達、ユーザーが1つのドキュメントを持っています:ユーザー1と友達も1つのドキュメントを持っています:フレンド1。

そのため、User1には「Friends/Friend1」というテキストの参照フィールドがあります。

Uはすべてのユーザーを取得でき、各ユーザーに対して次のようなマップを作成できます。

[
  {
    "User1":"Friend1"
  }
  {
    "Another User":"Another Friend"
  }
]
0
Tiago Pereira