anulamatamang
anulamatamang

Reputation: 23

How to get all Firebase Firestore documents created by a list of users?

I am building a soical media application using Firebase Firestore and React. I have a "posts" collection which stores post documents. In that post document, I store in a field the user ID of the creator of the post.

I also have a "users" collection which has user documents for authenticated users. In this user document I have a "friendList" array which is a list of user IDs.

I want to query for all posts created by the users in a "friendList" array and also listen for changes in the database.

I can get the querysnapshot for posts form a single user. But, I do not seem to find any solution for my problem.

Below is the code for my component where I need the posts:

export default function HomepageFeed({ friendList }) {
  const { currentUser } = useAuth();

  const [posts, setPosts] = useState([]);

  useEffect(() => {
    getPostsFromFriends(friendList);
  }, []);

  async function getPostsFromFriends(friendList) {
    const promises = [];

    promises.push(getPosts(currentUser.uid));

    for (let i = 0; i < friendList.length; i++) {
      promises.push(getPosts(friendList[i]));
    }

    const postsForHomepageFeed = await Promise.all(promises);
    setPosts(postsForHomepageFeed);
  }

  function getPosts(userId) {
    return new Promise((resolve, reject) => {
      db.collection('posts')
        .orderBy('timestamp', 'desc')
        .where('userId', '==', userId)
        .onSnapshot((snapshot) => {
          const data = snapshot.docs;
          if (data) resolve(data);
          else
            reject({
              error: `error getting posts from ${userId}`,
            });
        });
    });
  }

...render function here...
 <div className='feed_container'>
    {friendsPosts.map(({ id, post }) => {
        return (<Post
                key={id}
                id={id}
                ... /> )}  
</div>

Upvotes: 0

Views: 1062

Answers (1)

Dharmaraj
Dharmaraj

Reputation: 50830

You would have to fetch that friendList array from user's document and make new requests for fetching posts from those users.

const db = firebase.firestore()

const getUserFriends = async (userId) => {
  return (await db.collection("users").doc(userId).get()).data().friendList
}

const getFriendsPosts = async (friendUids) => {
  const postsCol = db.collection("posts")
  const requests = friendsUids.map(f => postsCol.where("userId", "==", f))
  const postsQSnaps = await Promise.all(requests)

  let posts = []

  postsQSnaps.forEach(qSnap => {
    posts = [...posts, ...qSnap.docs.map(p => ({ id: p.id, ...p.data() }))]
  })

  console.log(posts)
  return posts
}

Alternatively, you can in operator in query but if friendList array can contain more than 10 users, using Promise.all() as in the above code snippet might be easier.

Upvotes: 1

Related Questions