在Firebase中建模应用程序之类的聊天

时间:2016-09-01 02:11:51

标签: javascript firebase firebase-realtime-database nosql

我有一个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*/})

问题:

  1. 这是建模问题的正确方法吗?
  2. 如果是,是否有办法合并上述2个查询?

5 个答案:

答案 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子系统中为每个用户存储emaildisplayNamepasswordphotoURL。以下功能是您如何为基于密码的用户执行此操作。 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中详细了解如何以及为何这样做。