【问题标题】:Multiple Firestore queries, single promise / callback多个 Firestore 查询,单个承诺/回调
【发布时间】:2017-11-29 12:27:06
【问题描述】:

我了解 Firestore 不支持查询的逻辑 OR。 我的想法是创建多个查询并在客户端合并结果。 我正在开发一个新闻应用程序,我正在尝试获取所有包含我用户兴趣标签的文章(例如技术、音乐等) 一个普通用户有 20 个标签,所以我将提出 20 个不同的请求。

有没有人有链接多个请求并在所有结果到达时返回唯一承诺的经验。?

我正在使用 js sdk

我的数据结构:

文章(收藏)

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

所以我需要创建多个数据库请求,如下所示。

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
  });)
}

我试图弄清楚如何在每个请求完成时创建一个承诺/回调。

【问题讨论】:

    标签: firebase google-cloud-firestore


    【解决方案1】:

    您可以将每个数据库访问 Promise 保存在一个数组中,然后使用 Promise.all() 获取一个 Promise,该 Promise 在每个数据库访问完成时解析。 (此代码未经测试,可能包含一些语法错误,但它演示了这个想法。)

    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
    };
    

    【讨论】:

    • 这在 Java/Android 中怎么可能?
    【解决方案2】:

    这是一个对 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
       */
    
    })
    

    【讨论】:

      【解决方案3】:

      我能够使用以下代码实现我的目标...

      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);
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-02-25
        • 2016-07-23
        • 2015-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-15
        • 1970-01-01
        相关资源
        最近更新 更多