我有一个Firebase数据库结构问题。我的方案接近聊天应用程序。以下是具体细节
- users(node storing several users of the app)
- id1
name: John
- id2
name: Meg
- id2
name: Kelly
- messages(node storing messages between two users)
- message1
from: id1
to: id2
text: ''
- message2
from: id3
to: id1
text: ''
现在想象为单个用户构建对话视图。所以我想从特定用户那里获取所有消息 以及该特定用户
我现在写的如下:
let fromMessagesRef = firebase.database().ref('messages').orderByChild('from').equalTo(firebase.auth().currentUser.uid)
fromMessagesRef.once("value").then((snapshot) => {/* do something here*/})
let toMessagesRef = firebase.database().ref('messages').orderByChild('to').equalTo(firebase.auth().currentUser.uid)
toMessagesRef.once("value").then((snapshot) => {/* do something here*/})
问题:
答案 0 :(得分:7)
我会存储这样的数据:
- users(node storing several users of the app)
- id1
name: John
messages
message1: true
message2: true
- id2
name: Meg
messages
message1: true
message3: true
- id3
name: Kelly
messages
message2: true
message3:true
- messages(node storing messages between two users)
- message1
from: id1
to: id2
text: ''
- message2
from: id3
to: id1
text: ''
- message3
from: id2
to: id3
text: ''
Firebase建议存储此类内容。因此,在您的情况下,您的查询将是
let fromMessagesRef = firebase.database().child('users').child(firebase.auth().currentUser.uid).child('messages')
这使得它可以非常快,因为没有orderBy被完成。然后,您将遍历每条消息并从消息节点获取它的配置文件。
答案 1 :(得分:3)
您拥有的结构是建模此数据的一种可能方式。如果您正在构建这样的应用程序,我强烈推荐angularfire-slack教程。对数据建模的一种可能更快的方法是按照本教程https://thinkster.io/angularfire-slack-tutorial#creating-direct-messages
中的建议对数据建模{
"userMessages": {
"user:id1": {
"user:id2": {
"messageId1": {
"from": "simplelogin:1",
"body": "Hello!",
"timestamp": Firebase.ServerValue.TIMESTAMP
},
"messageId2": {
"from": "simplelogin:2",
"body": "Hey!",
"timestamp": Firebase.ServerValue.TIMESTAMP
}
}
}
}
}
在这种情况下,如果您选择这样做,则需要注意的一件事是,在查询之前,您需要对哪个用户将成为存储消息的“主要用户”进行排序。只要你确保每次都一样,你就应该好好去。
您可以对此结构进行一项改进,这是您已经指出的内容 - 展平您的数据并将消息移动到另一个节点 - 就像您在示例中所做的那样。
要回答你的第二个问题,如果你要保留这个结构,我认为你需要这两个查询,因为firebase不支持更复杂的OR
查询,允许你在同一时间。
答案 2 :(得分:2)
没有。您可以在Firebase Auth子系统中为每个用户存储email
,displayName
,password
和photoURL
。以下功能是您如何为基于密码的用户执行此操作。 o基于Auth的用户更容易。如果您要存储其他属性,例如age
,请将这些属性放在users
节点下,以及Firebase身份验证为您提供的每个用户uid
。
function registerPasswordUser(email,displayName,password,photoURL){
var user = null;
//NULLIFY EMPTY ARGUMENTS
for (var i = 0; i < arguments.length; i++) {
arguments[i] = arguments[i] ? arguments[i] : null;
}
auth.createUserWithEmailAndPassword(email, password)
.then(function () {
user = auth.currentUser;
user.sendEmailVerification();
})
.then(function () {
user.updateProfile({
displayName: displayName,
photoURL: photoURL
});
})
.catch(function(error) {
console.log(error.message);
});
console.log('Validation link was sent to ' + email + '.');
}
对于messages
节点,从Firebase实时数据库的push
方法中获取随机ID,并将其用作id
下每条消息的messages
。使用Firebase查询:
var messages = firebase.database().ref('messages');
var messages-from-user = messages.orderByChild('from').equalTo('<your users uid>');
var messages-to-user = messages.orderByChild('to').equalTo('<your users uid>');
messages-from-user.once('value', function(snapshot) {
console.log('A message from <your users uid> does '+(snapshot.exists()?'':'not ')+' exist')
});
messages-to-user.once('value', function(snapshot) {
console.log('A message to <your users uid> does '+(snapshot.exists()?'':'not ')+' exist')
});
在规则中为来自用户和消息的用户定义索引:
{
"rules": {
"messages": {
".indexOn": ["from", "to"]
}
}
}
答案 3 :(得分:2)
以下数据结构为您提供了更灵活的数据。我不建议存储用户来回发送的每条消息,而是建议将其存储在单独的节点中,并将messageID与参与对话的每个用户一起存储。
显然,您需要设置安全规则,以便其他用户无法在对话中看到对话。
通过这样做,我们不会在用户信息中创建深层链节点
- users(node storing several users of the app)
- id1
name: John
messages: [msID1, msID9]
- id2
name: Meg
messages: [msID1, msID7]
- id3
name: Kelly
messages: [msID9, msID7]
- messages(node storing messages between two users)
- msID1
from: id1
to: id2
text: ''
- msID7
from: id3
to: id2
text: ''
- msID9
from: id3
to: id1
text: ''
答案 4 :(得分:1)
Firebase实际上构建了一个名为Firechat的演示(和可扩展)聊天应用程序。提供了来源和文档,特别注意的是data structures上的部分。
虽然他们已经实施了聊天室,但您可以看到他们已经像许多其他答案一样扁平化了他们的数据结构。您可以在Firebase guide中详细了解如何以及为何这样做。