2017-11-29 3 views
0

Firestore가 쿼리에 대해 논리 OR을 지원하지 않는다는 것을 알고 있습니다. 제 생각은 클라이언트에서 여러 개의 쿼리를 만들고 결과를 병합하는 것입니다. 뉴스 앱을 개발 중이고 사용자의 관심 분야 태그 (예 : 기술, 음악 등)가 포함 된 모든 기사를 가져 오려고합니다 일반 사용자는 20 개의 태그를 가지고 있으므로 20 개의 다른 요청을 할 것입니다.복수의 Firestore 쿼리, 단일 약속/콜백

누구나 여러 요청을 연결하고 모든 결과가 도착하면 고유 한 약속을 반환하는 경험이 있습니까?

내가 JS SDK를

내 데이터 구조를 사용하고

:

제품 (컬렉션)

-article (document) 
--id: 10 
--time: 1502144665 
--title: "test title" 
--text: "test text" 
--tags(obj) 
---technology: 1502144665, 
---politics: 1502144665, 
---sports: 1502144665 

그래서 나는 다음과 같은 여러 DB 요청을 만들어야합니다.

user.tags = ["technology","politics","sports","architecture","business"]; 

for (var i = 0; i < user.tags.length; i++) { 
    db.collection('articles').where(user.tags[i], '>', 0).orderBy(user.tags[i])) 
    .get() 
    .then(() => { 
     // ... push to article array 
    });) 
} 

모든 요청이 완료 될 때 약속/콜백을 만드는 방법을 알아 내려고합니다.

답변

2

각 데이터베이스 액세스 약속을 배열에 저장 한 다음 Promise.all()을 사용하여 각 데이터베이스 액세스가 완료 될 때 해결되는 약속을 가져올 수 있습니다. (이 코드는 몇 가지 구문 오류가있을 수 있습니다, 테스트,하지만 아이디어를 보여줍니다되지 않습니다.)

user.tags = ["technology","politics","sports","architecture","business"]; 

var dbPromises = []; 
for (var i = 0; i < user.tags.length; i++) { 
    dbPromises.push(
     db.collection('articles') 
     .where(user.tags[i], '>', 0) 
     .orderBy(user.tags[i]) 
     .get() 
); 
} 

Promise.all(dbPromises) 
    .then(() => { 
     // ... push to article array 
}; 
+0

Java/Android에서는 어떻게 가능합니까? –

0

내가 다음 코드를 사용하여 내 목표를 달성 할 수 있었다 ...

window.firebaseData = []; 
window.firebaseQueue = []; 
var testTags = ["technology","design","entertainment","world","fashion","food","architecture","science","movies","graphics","gaming","photography","finance"]; 

for (var i = 0; i < testTags.length; i++) { 
    window.firebaseQueue.push(testTags[i]); 
    var tagString = "tags."+testTags[i]; 
    window.db.collection('data').where(tagString, '>', 0).orderBy(tagString).limit(100) 
    .get() 
    .then(function(querySnapshot) { 
     updateQueue(testTags[i],true); 
     querySnapshot.forEach(function(doc) { 
     var data = doc.data(); 
     window.firebaseData.push(data); 
     console.log(doc.id, " => ", doc.data()); 
     }); 
    }) 
    .catch(function(error) { 
     console.log(error); 
     updateQueue(testTags[i],false); 
    }); 
} 


function updateQueue(tag, success){ 
    if(success){ 
    arrayRemove(window.firebaseQueue, tag); 
    if(window.firebaseQueue.length < 1){ 
     console.log("All finished"); 
    } 
    }else{ 
    console.log("Failed: " + tag); 
    } 
} 
1

여기에 복잡성을 줄이기 위해 일부 기능적 패러다임을 사용하는 ES6 친숙한 버전입니다

let articles = db.collection('articles') 

user.tags = [ 
    'technology', 
    'politics', 
    'sports', 
    'architecture', 
    'business' 
] 

// map each tag to a firestore query 
let queries = users.tags.map(tag => { 
    return articles.where(tag, '>', 0).orderBy(tag).get() 
}) 



/* 
    Use Promise.all to aggregate the results 
    and wait for all of them to complete 
*/ 

Promise.all(queries).then((querySnapshots) => { 

    /* 
    querySnapshots is an Array[QuerySnapshot] 
    reduce all our querySnapshots to only their DocumentReferences 
    */ 

    return querySnapshots.map(qs => qs.docs) 
         .reduce((acc, docs) => [...acc, ...docs]) 

}).then((matchingArticleRefs) => { 

    /* 
    matchingArticleRefs is now an Array[DocumentReferences] from firestore 
    if no documents matched the queries above it will be an empty array 
    */ 

}) 
관련 문제