【问题标题】:How can I get the first document ID from a firebase collection, which is not equal to a given ID?如何从不等于给定 ID 的 firebase 集合中获取第一个文档 ID?
【发布时间】:2020-10-20 06:35:31
【问题描述】:

我有 'users' 集合,其中包含每个用户 ID 的文档。我还使用经过身份验证的用户 ID(匿名登录)将当前用户 ID 存储在 userID 变量中。

我需要根据最低值的计数器(此集合中的文档数据项)获取一个文档 ID(不是文档数据),并将其存储在名为“receiverID”的变量中,但如果文档 ID 等于当前用户的 ID,然后我想获取下一个可用的 ID。

例如,如果我的平台上有 3 个用户(A、B 和 C)并且存在以下“计数器”值:

  • A:1,B:2,C:3

理论上,当 A 查询集合时,他们会得到自己的 doc ID。然后我需要在“用户”集合中获取第二个文档。

我从以下开始,但卡住了:

receiverID = db.collection('users').orderBy('Questions Received','asc').limit(1)

此外,这在事件侦听器上触发(当用户提交问题时),因此必须在函数的下一部分之前解析“receiverID”。这是我的事件监听器的样子:

const sayForm = document.querySelector('#say-form');
sayForm.addEventListener('submit', (e) => {
    e.preventDefault();

    db.collection('message').add({
        message: sayForm.sayInput.value,
        time: firebase.firestore.FieldValue.serverTimestamp(),
        sender: userID,
        currentReceiver: receiverID,
        received: 1
    })
    .catch(function(error) {
        console.error("Error adding document: ", error);
    });
});

【问题讨论】:

  • 您介意使用反引号修复缩进并为单个文档中的属性添加更多格式吗?改进格式也有助于澄清问题
  • @ralemos 能够格式化。我希望现在更清楚了。

标签: javascript firebase asynchronous google-cloud-firestore


【解决方案1】:

Firestore 中的查询没有不同的运算符,因此您必须获取第一个文档,如果不是预期的 documentID,则获取下一个文档,依此类推。您可以通过执行以下操作来做到这一点:

receiverID = this.getNextReceiver();

function getNextReceiver() {
    db.collection('users')
      .orderBy('Questions Received','asc')
      .limit(1)
      .get()
      .then(function (doc) {
          if(doc.id == userID){
              var validId = false;
              var tempDoc = doc;
              while(!validId){
                  db.collection('users')
                    .orderBy('Questions Received','asc')
                    .startAfter(tempDoc)
                    .limit(1)
                    .get()
                    .then(function (newDoc) {
                        if(newDoc.id != userID){
                            validId = true;
                            return newDoc.id;
                        }
                        tempDoc = newDoc;
                    });
                  
              }
          }
          return doc.id;
      });
}

所有这些都是同步运行的。关于您的提交,无法保证会填充 receiverID,因为它是由事件触发的,因此您必须创建一个不填充该值的场景,或者在填充之前阻止用户交互。

注意:所有这些代码都未经测试,但对您来说应该是一个很好的起点。

【讨论】:

  • 上面的小改动(去掉最后一个子函数中额外的“(”)。这是一个很好的起点,绝对比我想象的更有效(使用等待时间和所有)。将“receiverID”变量放在函数之后感觉更安全。但是,当我现在尝试调用“getNextReceiver”函数时遇到了这个问题。这是错误:VM1084:1 Uncaught ReferenceError:getNextReceiver 未在 中定义: 1:1
  • 作为次要问题,您在哪里查找如何解决此类错误?
  • 我编辑了答案并修复了您遇到的错误(调用函数时缺少this.)并删除了额外的(,感谢您指出这一点,它应该在工作,在忙。事实上,我还发现使用promise.then() 比等待返回更好,特别是在你必须在承诺之上堆叠承诺的情况下,我认为这不太容易出错。
  • 对于你的第二个问题,我通常会进行谷歌搜索,将我指向其他一些具有类似问题和解决方案的社区帖子,我会尝试适应,博客和文档通常也会有所帮助。如果解决了您面临的问题,请记得点赞并接受答案。
  • 尝试记录在getNextReceiver() 函数中返回的值,如果它们有值,那么这意味着您在填充之前记录了receiverID。您可以通过在函数内部填充 receiverID 并且不返回值来缓解这种情况。
【解决方案2】:

我能够通过执行以下操作来解决它:

function getNextReceiver() {
  db.collection('users')
    .orderBy('Messages Received','asc')
    .limit(2)
    .get()
    .then(querySnapshot => {
      let x = querySnapshot.docs[0].id;
      let y = querySnapshot.docs[1].id;
      if (x == userID) {
        receiverID = y
      } else {
        receiverID = x;
      }
    });
    
}

getNextReceiver();

通过将搜索结果限制为 2 并将它们保存在一个变量中,我能够与“userID”进行比较,并将“receiverID”相应地设置为不匹配的那个。

【讨论】:

    猜你喜欢
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 2020-04-14
    • 2020-11-01
    • 2021-01-30
    • 2018-04-20
    • 2021-09-28
    相关资源
    最近更新 更多