web-dev-qa-db-ja.com

Firestoreでネストされた単一クエリを操作する

最近、データモデルをFirebaseからFirestoreに移動しました。すべてのコードは機能していますが、一部のデータを取得するためのネストされたクエリに関して厄介な問題があります。ここにポイントがあります:

現在、この部分のデータモデルは次のようになっています(はい!別のフォロワー/フィードの例):

_{
  "Users": { //Collection
    "UserId1" : { //Document
      "Feed" : { //Subcollection of Id of posts from users this user Follow
        "PostId1" : { //Document
          "timeStamp" : "SomeDate"
        },
        "PostId2" : {
          "timeStamp" : "SomeDate"
        },
        "PostId3" : {
          "timeStamp" : "SomeDate"
        }
      }
      //Some data
    }
  },
  "Posts":{ //Collection
    "PostId1":{ //Document
      "Comments" :{ //Subcollection
        "commentId" : { //Document
          "authorId": "UserId1"
          //comentsData
        }
      },
      "Likes" : { //Subcollection
        "UserId1" : { //Document
          "liked" : true
        }       
      }
    }
  }
}
_

私の問題は、ユーザーのフィードの投稿を取得するには、次の方法でクエリを実行する必要があることです。

  • フィードからtimeStampまでに最後のXドキュメントの注文者を取得する

feedCol(userId).orderBy(CREATION_DATE, Query.Direction.DESCENDING).limit(limit)

  • その後、リストから取得した各投稿に対して単一のクエリを実行する必要があります:workoutPostCol.document(postId)

  • これで各投稿のデータが手に入りましたが、著者のユーザー名、写真、ポイントなどを撮影したいのですが、これは異なるDocumentにあるため、各authorId投稿のリストで取得userSocial(userId).document(toId)

  • 最後に、それほど重要ではないが、現在のユーザーが既にその投稿を気に入っているかどうかを知る必要があるので、各投稿に対してもう一度クエリを実行し(再度)、userIdが_posts/likes/{userId}_内にあるかどうかを確認する必要があります

現時点ではすべてが機能していますが、Firestoreの価格はデータベース呼び出しの数に依存し、クエリがより単純にならないこと、それが自分のデータだけなのかわかりませんモデルはこの種のデータベースには適していません。通常のSQLに移動するか、再びFirebaseに戻る必要があります。

:いいね、フィードなどのこのサブコレクションをユーザー内の配列リストに移動したり、ドキュメントを投稿したりする方がはるかに簡単になることはわかっていますが、ドキュメントの制限は1MBそしてこれが大きくなると、将来クラッシュします。一方、Firestoreは、サブドキュメントクエリ(まだ)または複数のORを使用するwhereEqualTo句を許可しません。

joinsqueriesCollectionsにするために、この種の_ID's_関係を保存する簡単な方法を探しているユーザーからの多くの投稿を読みました。 Arraylistsは素晴らしいでしょうが、1MBの制限はそれを多くに制限します。

誰かがこれを明確にするか、少なくとも新しいことを教えてくれることを願っています。多分私のモデルはただのがらくたで、これを行う簡単で簡単な方法はありますか?または、非SQLデータベースでは私のモデルは不可能かもしれません。

使用方法によってはEdgeケースが存在する場合があるため、これで問題が完全に解決されるかどうかは100%確信できません。しかし、5分の素早い思考で、次のことが問題を解決できると思います。

Instagramに似たモデルの使用を検討できます。私の記憶が私によく役立つなら、彼らが使用するのはeventsベースのコレクションです。この特定のコンテキストでeventsとは、ユーザーが実行するすべてのアクションを意味します。したがって、commentはイベント、likeはイベントなどです。

これにより、合計3つのメインコレクションが必要になります。

users
-- userID1
---- userdata (profile pic, bio etc.)
---- postsByUser : [postID1, postID2]
---- followedBy : [userID2, ... ]
---- following : [userID2, ... ]
-- userID2
---- userdata (profile pic, bio etc.)


posts
-- postID1 (timestamp, so it's sortable)
---- contents
---- author : userID1
---- authorPic : authorPicUrl
---- authorPoints : 12345
---- taggedUsers : []
---- comments
------ comment1 : { copy of comment event }
---- likes : [userID1, userID2]
-- postID2 (timestamp)
---- contents
... 


events
-- eventID1
---- type : comment
---- timestamp
---- byWhom : userID
---- toWhichPost : postID
---- contents : comment-text
-- eventID2
---- type : like
---- timestamp
---- byWhom : userID
---- toWhichPost : postID

User-bioページの場合、usersをクエリします。

ニュースフィードでは、過去1日間(または任意の期間)にユーザーがフォローしているユーザーIDによるすべての投稿に対してpostsをクエリします。

アクティビティフィードページ(コメント/いいね!など)では、過去1日間(または任意の期間)に制限されたユーザーIDに関連するeventsをクエリします

最後に、ユーザーがスクロールするときに(またはその日に新しいアクティビティがない場合)投稿/イベントの翌日をクエリします

繰り返しになりますが、これはただの簡単な考えです。SOFの長老たちは通常これらを十字架につける習慣があるので、この答えに欠陥がある場合はSOFの仲間を許してください:)

それがフランシスコを助けることを願って、

幸運を!

19
johnozbay