【问题标题】:Firebase Realtime Database - orderByChild().equalTo() does not return expected nodeFirebase 实时数据库 - o​​rderByChild().equalTo() 不返回预期节点
【发布时间】:2023-03-23 07:21:01
【问题描述】:

我的 Firebase 实时数据库数据结构如下,我想在“联系人”和“笔记”节点中将“-preliminaryId”替换为“-ultimateId123”。为此,我将删除旧节点并替换新节点。

"prel":{
  "-preliminaryId": {
    "email" : "hello@bye.com"
  }
},
"contacts": {
  "-ABC": {
     "-BCD": {
       "email": "bye@nowhere.com",
       "uid" : "-123456WWWXYz"
     },
     "-preliminaryId": {
       "email": "hello@bye.com",
       "uid": "-preliminaryId"
     }
  }
},
"notes": {
  "-noteIdone": {
    "access": {
      "members": {
        "-preliminaryId": 1
      }
    }
  },
  "-noteIdtwo": {
    "access": {
      "members": {
        "-realId1234": 1
      }
    }
  }
}

电子邮件“hello@bye.com”的新 ID 应为“-ultimateId123”。 (我无法将电子邮件作为密钥存储在 Firebase 实时数据库中。)

我首先获取要替换的初始 id。

  const prelSnap = await dbRoot.child('prel').orderByChild('email').equalTo('hello@bye.com').once('value')
  const prelData= prelSnap.val()
  console.log('prelData', prelData)
  const oldId = Object.keys(prelData)[0]

prelData 变量将是

{ -preliminaryId: { email: 'hello@bye.com' } } 

但是,我更希望它只是

{ email: 'hello@bye.com' }

所以我可以通过prelSnap.key 而不是Object.keys(prelData)[0] 获得oldId

但是,我真正的障碍是获取contacts

  const contactSnaps = await dbRoot.child('contacts').orderByChild(`${oldId}/uid`).equalTo(oldId).once('value')
  console.log('contactSnaps', contactSnaps.numChildren())
  contactSnaps.forEach((contact)=>{
    console.log('contactData', contact.val())
    const userId = Object.keys(contactData)[0] 
    ...
    // Replace the contact node
    myPromises.push(dbRoot.child(`contacts/${userId}/${newId}`).set(contactObj)) // Create new contact data
    myPromises.push(dbRoot.child(`contacts/${userId}/${oldId}`).remove()) // Delete old contact
    ...
  })

这将为我提供所有联系人。从console.log('contactData', contact.val()) 注销将是:

numChildren 1

contactData {
   "-BCD": {
     "email": "bye@nowhere.com",
     "uid" : "-123456WWWXYz"
   },
   -preliminaryId: {
     "email": "hello@bye.com",
     "uid": "-preliminaryId"
   }
}

硬编码示例:

const contactSnaps = await dbRoot.child('contacts').orderByChild('-preliminaryId/uid').equalTo('-preliminaryId').once('value')
console.log('contactSnapsHC', contactSnaps.numChildren())
contactSnaps.forEach((contact)=>{
  const contactData = contact.val()
  console.log('contactDataHC', contactData)
})

上述硬编码示例的输出:

contactSnapsHC 1
contactDataHC { -BCD: { email: "bye@nowhere.com", uid : "-123456WWWXYz" }, -preliminaryId: { email: "hello@bye.com", uid: "-preliminaryId" } }

我的猜测是这可能与我第一次查询的问题有关?

当对笔记执行相同类型的查询时,一切正常。

nodeSnaps = await dbRoot.child('notes').orderByChild(`access/members/${oldId}`).equalTo(1).once('value')
console.log('notes', nodeSnaps.numChildren())
nodeSnaps.forEach((node)=>{
  console.log('notesData', node.val())
  ...
}

这里的输出将是:

notes 1
notesData { "access": { "members": { "-preliminaryId": 1 } } }

我希望前两个查询返回与notes 查询相同节点级别的结果。

如何查询数据库以返回如下所示的结果?

prelData { email: 'hello@bye.com' }
contactData { email: 'hello@bye.com', uid: '-preliminaryId' }

亲切的问候 /K

【问题讨论】:

  • firebase 不允许重命名节点中的“密钥”,我建议这样做。您已删除整个节点并重新创建它
  • this 是一个很好的参考吗?
  • 嗨!是的,我的计划是删除旧节点并用新节点替换它! :D
  • 如果我理解正确,你是说这个查询const contactSnaps = await dbRoot.child('contacts').orderByChild(${oldId}/uid).equalTo(oldId) 没有给出预期的结果。如果这确实是问题所在,您能否使用oldId 的硬编码值重现该问题,并在代码中提供该值,以便这样。可以尝试重现吗?
  • 嗨@FrankvanPuffelen - 谢谢你的回复!我在打印输出中添加了一个硬编码示例。 /K

标签: javascript firebase-realtime-database


【解决方案1】:

我认为您的困惑在于查询返回的内容:

dbRoot.child('contacts').orderByChild('-preliminaryId/uid').equalTo('-preliminaryId')

Firebase 查询在平面列表上运行。由于您查询contacts,返回的节点将是contacts 的子节点。具体来说,它返回contact 的任何子节点,其中存在属性-preliminaryId/uid,其值为-preliminaryId。在您的示例中,contacts/-ABC 的节点是正确的,这就是查询为我返回的内容。


例如,当我添加另一个与ABC 相同级别的兄弟节点时:

"contacts": {
  "-ABC": {
     "-BCD": {
       "email": "bye@nowhere.com",
       "uid" : "-123456WWWXYz"
     },
     "-preliminaryId": {
       "email": "hello@bye.com",
       "uid": "-preliminaryId"
     }
  },
  "DEF": {
     "-HKI": {
       "uid": "another id"
     }
  }
},

在这种情况下,您的查询仍然只返回 -ABC 节点,因为这是唯一存在 -preliminaryId/uid 且值正确的节点。

有关这方面的工作示例,请参阅:https://jsbin.com/wivukeq/edit?js,console

【讨论】:

  • 啊,好的。这就说得通了! :) 我现在看到“笔记”的结构有所不同——少了一层——这就是一切的不同之处! :D /K
  • 当您说“Firebase 查询在平面列表上运行”时,我想我开始理解您的意思了;D 最后!再次 - 非常感谢! /K
  • 当然可以。您可能还想在这里查看我的答案,因为您通常执行的动态查询类型不会扩展到长列表。 stackoverflow.com/questions/40656589/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
  • 1970-01-01
相关资源
最近更新 更多