2017-12-22 10 views
1

나는 다음과 같은 구조의 클라우드 경우 FireStore DB를 가지고 :Cloud Firestore 쿼리에서 여러 문서를 조인하는 방법은 무엇입니까?

  • 사용자
    • [UID]
      • 이름 : "테스트 사용자"
  • 게시물
    • [id]
      • 콘텐츠 : "Just some test post."
      • 소인 (12 월 22, 2017)
      • UID : UID]

실제 DB에 존재하는 데이터가 더는 상기 그냥 수집/문서를 도시/필드 구조.

내 웹 앱에서 내가 게시물을 표시하고 게시 한 사용자의 이름을 표시하려는보기가 있습니다. 나는 게시물을 가져 오기 위해 아래의 쿼리를 사용하고 있습니다 :

let loadedPosts = {}; 
posts = db.collection('posts') 
      .orderBy('timestamp', 'desc') 
      .limit(3); 
posts.get() 
.then((docSnaps) => { 
    const postDocs = docSnaps.docs; 
    for (let i in postDocs) { 
    loadedPosts[postDocs[i].id] = postDocs[i].data(); 
    } 
}); 

// Render loadedPosts later 

내가 뭘 원하는 것은 포스트의 UID 필드에 저장된 UID에 의해 사용자 개체를 조회하고, 해당 loadedPosts 객체로 사용자 이름 필드를 추가입니다 . 한 번에 하나의 게시물 만로드하는 경우 문제가되지 않으며 개체가있는 쿼리를 다시 기다리고 .then() 함수에서 사용자 문서에 다른 쿼리를 만드는 등의 작업을 수행 할 수 있습니다.

그러나 여러 게시물 문서를 한 번에 가져오고 있기 때문에 올바른 게시물을 .get() 각 게시물의 user/[uid] 문서에서 호출 한 후 올바른 사용자를 올바른 게시물로 매핑하는 방법을 찾는 데 어려움을 겪고 있습니다. .

누구든지이 문제에 대한 우아한 해결책을 생각할 수 있습니까?

답변

4

1 명의 사용자 문서 호출을하고 필요한 게시물을 호출합니다.

let users = {} ; 
let loadedPosts = {}; 
db.collection('users').get().then((results) => { 
    results.forEach((doc) => { 
    users[doc.id] = doc.data(); 
    }); 
    posts = db.collection('posts').orderBy('timestamp', 'desc').limit(3); 
    posts.get().then((docSnaps) => { 
    docSnaps.forEach((doc) => { 
    loadedPosts[doc.id] = doc.data(); 
    loadedPosts[doc.id].userName = users[doc.data().uid].name; 
    }); 
}); 
+0

2 대신에 4가 호출됩니다. – saricden

+3

마지막 3 개의 게시물을 작성한 사용자가 아닌 모든 사용자를로드합니다. 이 기능은 개발 중에는 제대로 작동하지만 더 많은 사용자를 추가하면 더 많은 불필요한 데이터가로드됩니다. –

3

그것은 나에게 매우 간단 보인다

let loadedPosts = {}; 
posts = db.collection('posts') 
      .orderBy('timestamp', 'desc') 
      .limit(3); 
posts.get() 
.then((docSnaps) => { 
    docSnaps.forEach((doc) => { 
    loadedPosts[doc.id] = doc.data(); 
    db.collection('users').child(doc.data().uid).get().then((userDoc) => { 
     loadedPosts[doc.id].userName = userDoc.data().name; 
    }); 
    }) 
}); 

당신이 사용자를 여러 번로드 방지하려면 사용자 데이터 클라이언트 측을 캐시 할 수 있습니다. 이 경우 사용자로드 코드를 도우미 함수로 인수 분해하는 것이 좋습니다. 그러나 위의 변형이 될 것입니다.

+0

대단한 테스트를 거쳐 완벽하게 작동합니다. 나는 이것에 접근하면 doc.id가 사용자 get(). then()에 대한 모든 호출에 대한 마지막 반복문의 ID가되고 결국 내 부분의 루프에서 콜백을 정의하는 것에 대한 오해가 일어날 것이라고 생각했다. – saricden

-1

하나의 userdoc 쿼리와 필요한 postsdoc 호출 만 수행합니다.

+0

죄송 합니다만 이것은 parmigiana의 원래 답변에서 .limit (3)을 뺀 것과 동일합니다. 다른 사람의 답변을 복사해서는 안됩니다. – saricden