【问题标题】:Realtime database clould function : why is this query returning null?实时数据库云功能:为什么这个查询返回 null?
【发布时间】:2021-06-28 05:01:33
【问题描述】:

我有一个包含名称字段的邮箱表,我想在用户表中更改名称时更新/插入该名称。查询总是返回 null。

在用户更改表监听器中:

exports.updateMailboxes = functions.database.ref('/users/{userId}')
  .onUpdate((change, context) => {
  const rec = change.after.val();

  functions.logger.log('updateMailboxes check ', String(context.params.userId));

  return admin.database().ref('/mailbox')
    .orderByChild('toID')
    .equalTo(String(context.params.userId))
    .once('value', (snapshot) => {
      functions.logger.log('updateMailboxes ', JSON.stringify(snapshot.val()));
      snapshot.forEach((child) => {
        functions.logger.log('updateMailboxes child ', JSON.stringify(child.val()));
        child.ref.update({name: rec.username});
      });
  });
});

我什至像这样在 equalTo 中硬编码一个值:

.equalTo("f3EXPNBjuecmdViCKZF1FduTrXd2")

它仍然返回 null。

orderByChild 本身就可以工作。

根据 Dharmaraj 的回答,我也尝试按键查询:

exports.updateMailboxes = functions.database.ref('/users/{userId}')
  .onUpdate((change, context) => {
  const rec = change.after.val();

  functions.logger.log('updateMailboxes check ', String(context.params.userId));

  return admin.database().ref('/mailbox/{ownerID}')
    .orderByKey()
    .equalTo(context.params.userId)
    .once('value').then((snapshot) => {
      functions.logger.log('updateMailboxes ', JSON.stringify(snapshot.val()));
      snapshot.forEach((child) => {
        functions.logger.log('updateMailboxes child ', JSON.stringify(child.val()));
        child.ref.update({name: rec.username});
      });
  });
});

它仍然返回 null。

我做错了什么?

【问题讨论】:

  • 邮箱的用途是什么?如果您正在构建一个消息收件箱,您不会显示发送给两个用户的最新消息,而不管是谁发送的?
  • 您好,当然可以——第一条记录显示给 user1,第二条记录显示给 user2——“toID”实际上应该是“otherID”

标签: javascript firebase firebase-realtime-database


【解决方案1】:

看起来该值与该节点的键相同,因此您可以使用orderByKey

firebase.database().ref(`/mailbox/{senderID}`).orderByKey().equalTo(context.params.userId).once("value").then((snap) => {
  console.log(snap.val());
})

根据您的数据库结构,您必须在ref 中提及发件人ID。您可能必须存储已向特定用户发送电子邮件的用户 ID。如果有人向 toID 'myUserID1' 发送邮件,那么您必须将发件人的 ID 存储在单独的节点中。

当您的云函数运行时,首先获取该节点,以便您知道应该更新邮箱节点中的名称的节点。

【讨论】:

  • 您好,感谢您的回答。我试过了,它仍然返回 null,我已经更新了我的问题。
【解决方案2】:

看看这个查询:

admin.database().ref('/mailbox')
  .orderByChild('toID')
  .equalTo(String(context.params.userId))

您所要求的是将/mailbox 的孩子按toID 的值排序。由于/mailbox 下的每个孩子都没有"toID" 的值,因此查询对这些孩子中的每一个使用null 的值(见下文),然后按键按字典顺序对它们进行排序(更多信息:Sorting with orderByChild )。这就是为什么当您更改查询以查找 "toID" 是所需用户的结果时没有得到任何结果的原因。

{
  "mailbox": {
    "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": {
      "gMVleaAuVbhGnROsBBkMS6gFum62": {
        // message data
      },
      "Wde7E2ONDFfolUHGFb5OipDgMpN2": {
        // message data
      },
      // "toID": null
    },
    "gMVleaAuVbhGnROsBBkMS6gFum62": {
      "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": {
        // message data
      },
      "Wde7E2ONDFfolUHGFb5OipDgMpN2": {
        // message data
      },
      // "toID": null
    },
    "Wde7E2ONDFfolUHGFb5OipDgMpN2": {
      "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": {
        // message data
      },
      "gMVleaAuVbhGnROsBBkMS6gFum62": {
        // message data
      },
      // "toID": null
    }
  }
}

使用您当前的数据库结构,您需要获取所有/mailbox,然后筛选数据以查找针对所需用户的消息。因为"toID" 与当前结构中该节点的键具有相同的值,所以我们可以搜索具有给定 ID 作为其子节点的节点。这可以使用以下查询来完成:

admin.database().ref(`/mailbox`)
  .orderByChild(context.params.userId)
  .startAfter(null) // skip nodes that don't have this user

重要提示:这对许多用户来说在规模上的表现很糟糕。即使您可以使用".indexOn" 为每个用户创建索引,但这是不切实际的。

要提高此类操作的性能,您需要存储有关谁向给定用户发送消息的信息。

{
  "mailboxReceivedFrom": {
    "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": {       // <- user ID who received the message
      "gMVleaAuVbhGnROsBBkMS6gFum62": true, // <- user ID who sent the message
      "Wde7E2ONDFfolUHGFb5OipDgMpN2": true
    },
    "gMVleaAuVbhGnROsBBkMS6gFum62": {
      "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": true,
      "Wde7E2ONDFfolUHGFb5OipDgMpN2": true,
    },
    "Wde7E2ONDFfolUHGFb5OipDgMpN2": {
      "KG0XjVNQ2Ka1offWN2VH3YbNqNx1": true,
      "gMVleaAuVbhGnROsBBkMS6gFum62": true
    }
    // Note: You could store the timestamp of the most recent message instead for sorting
  }
}
const userId = String(context.params.userId);
const username = rec.username;

return admin.database().ref('/mailboxReceivedFrom')
  .child(userId)
  .once('value')
  .then((querySnapshot) => {
    // prepare object to hold updates
    const pendingUpdates = {};

    // for each child, queue updating the username
    querySnapshot.forEach((childSnapshot) => {
      const path = childSnapshot.key + "/" + userId + "/name";
      pendingUpdates[path] = username;
    })

    // make changes to the database all at once
    return admin.database.ref("/mailbox")
      .update(pendingUpdates);
  })
  .catch((err) => {
    console.error("Failed to apply username change for user #" + userId, err);
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-01
    • 2019-09-11
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    相关资源
    最近更新 更多