【问题标题】:In Firebase when using push() How do I pull the unique ID在 Firebase 中使用 push() 时如何提取唯一 ID
【发布时间】:2013-05-14 06:34:46
【问题描述】:

我正在尝试从 Firebase 数据库中添加/删除条目。我想将它们列出在要添加/修改/删除的表中(前端),但我需要一种唯一标识每个条目的方法,以便修改/删除。 Firebase 在使用 push() 时默认添加一个唯一标识符,但我没有看到任何有关如何在 API 文档中选择此唯一标识符的内容。这甚至可以做到吗?我应该使用 set() 来创建唯一 ID 吗?

我用他们的教程把这个简单的例子放在一起:

<div id='messagesDiv'></div>
<input type='text' class="td-field" id='nameInput' placeholder='Name'>
<input type='text' class="td-field" id='messageInput' placeholder='Message'>
<input type='text' class="td-field" id='categoryInput' placeholder='Category'>
<input type='text' class="td-field" id='enabledInput' placeholder='Enabled'>
<input type='text' class="td-field" id='approvedInput' placeholder='Approved'>
<input type='Button' class="td-field" id='Submit' Value="Revove" onclick="msgRef.remove()">

<script>
var myDataRef = new Firebase('https://unique.firebase.com/');

  $('.td-field').keypress(function (e) {
    if (e.keyCode == 13) {
      var name     = $('#nameInput').val();
      var text     = $('#messageInput').val();
      var category = $('#categoryInput').val();
      var enabled  = $('#enabledInput').val();
      var approved = $('#approvedInput').val();
      myDataRef.push({name: name, text: text, category: category, enabled: enabled, approved: approved });
      $('#messageInput').val('');
    }
  });
  myDataRef.on('child_added', function(snapshot) {
    var message = snapshot.val();
    displayChatMessage(message.name, message.text, message.category, message.enabled, message.approved);
  });
  function displayChatMessage(name, text, category, enabled, approved, ) {
    $('<div/>').text(text).prepend($('<em/>').text(name+' : '+category +' : '+enabled +' : '+approved+ ' : ' )).appendTo($('#messagesDiv'));
    $('#messagesDiv')[0].scrollTop = $('#messagesDiv')[0].scrollHeight;
  };
</script>

现在假设我有三行数据:

fred : 1 : 1 : 1 : test message 1
fred : 1 : 1 : 1 : test message 2
fred : 1 : 1 : 1 : test message 3

如何唯一标识第 2 行?

在 Firebase 数据库中,它们如下所示:

-DatabaseName
    -IuxeSuSiNy6xiahCXa0
        approved: "1"
        category: "1"
        enabled: "1"
        name: "Fred"
        text: "test message 1"
    -IuxeTjwWOhV0lyEP5hf
        approved: "1"
        category: "1"
        enabled: "1"
        name: "Fred"
        text: "test message 2"
    -IuxeUWgBMTH4Xk9QADM
        approved: "1"
        category: "1"
        enabled: "1"
        name: "Fred"
        text: "test message 3"

【问题讨论】:

    标签: javascript jquery firebase


    【解决方案1】:

    对于发现此问题并使用Firebase 3+ 的任何人,您在推送后获取自动生成的对象唯一ID 的方式是使用承诺快照上的key 属性(非方法):

    firebase
      .ref('item')
      .push({...})
      .then((snap) => {
         const key = snap.key 
      })
    

    Firebase docs 中了解更多信息。

    附带说明,那些考虑生成自己的唯一 ID 的人应该三思而后行。它可能具有安全性和性能影响。如果您不确定,请使用 Firebase 的 ID。它包含一个时间戳,并具有一些开箱即用的简洁安全功能。

    更多信息here:

    push() 生成的唯一键按当前时间排序,因此生成的项目列表将按时间顺序排序。密钥也被设计成不可猜测的(它们包含 72 个随机位的熵)。

    【讨论】:

    • 天啊。非常感谢。在我找到你的简单答案之前,你不知道这是多么痛苦。
    • 这是有效的,接受的答案必须替换为这个
    【解决方案2】:

    要获取任何快照的“名称”(在本例中为 push() 创建的 ID),只需像这样调用 name():

    var name = snapshot.name();
    

    如果你想得到 push() 自动生成的名字,你可以在返回的引用上调用 name(),像这样:

    var newRef = myDataRef.push(...);
    var newID = newRef.name();
    

    注意: snapshot.name() 已被弃用。查看其他答案。

    【讨论】:

    • 这做了一些事情,我只是不确定是什么......它返回的值看起来像唯一标识符,但每次刷新页面时它们都不同。例如,-Iuy2dANtFBZ-OK7I-XK 将变为 -Iuy2dAPFfOkgSy7bLFo,然后变为 -Iuy2dAPFfOkgSy7bLFp。每次我刷新页面时它都会改变每一行。
    • 我仍然不确定为什么,但是关于您的示例的某些内容每次都会产生新的错误键。经过一番挖掘,我使用了 var message = snapshot.val(); message.id = 快照.name();。你把我带到那里,如果你想更新你的答案或详细说明可能出了什么问题,我很乐意接受你的回答。
    • 他认为您想在推送新聊天时(即在按键上)时获取引用的名称,而不是在加载之前保存的聊天时。这有意义吗?
    • 谢谢!是的,我在凌晨 3 点左右发现了这一点。我现在正在生成自己的递增键并将最后一个键存储在配置对象中。现在更容易理解了。
    • 嘿 Front_end_dev 你如何设置增量密钥可以共享。
    【解决方案3】:

    snapshot.name() 已被弃用。请改用key。任何 DataSnapshot 上的 key 属性(表示 Firebase 根的除外)将返回生成它的位置的键名。在您的示例中:

    myDataRef.on('child_added', function(snapshot) {
        var message = snapshot.val();
        var id = snapshot.key;
        displayChatMessage(message.name, message.text, message.category, message.enabled, message.approved);
    });
    

    【讨论】:

    • 请注意,key 现在是属性,而不是 DataSnapshot 上的方法:firebase.google.com/docs/reference/js/…
    • @Andrew Lee。只是好奇,作为提出原始问题的人。如果先前接受的答案已贬值,是否认为更改接受的答案是不好的形式?这里的 Stack 交换礼仪是什么?
    • 据我所知,更改已接受的答案没有错。
    【解决方案4】:

    要在push() 之后获得uniqueID,您必须使用此变体:

    // Generate a reference to a new location and add some data using push()
     var newPostRef = postsRef.push();
    // Get the unique key generated by push()
    var postId = newPostRef.key;
    

    当您push() 并使用此引用的.key 时,您会生成一个新的Ref,您可以获得uniqueID

    【讨论】:

      【解决方案5】:

      正如@Rima 指出的那样,key() 是获取分配给您的push() 的 ID firebase 的最直接方法。

      但是,如果您希望取消中间人,Firebase 发布了一个带有 ID 生成代码的要点。它只是当前时间的一个函数,这就是它们如何保证唯一性,即使没有与服务器通信。

      这样,您可以使用generateId(obj)set(obj) 来复制push() 的功能

      Here's the ID function:

      /**
       * Fancy ID generator that creates 20-character string identifiers with the following properties:
       *
       * 1. They're based on timestamp so that they sort *after* any existing ids.
       * 2. They contain 72-bits of random data after the timestamp so that IDs won't collide with other clients' IDs.
       * 3. They sort *lexicographically* (so the timestamp is converted to characters that will sort properly).
       * 4. They're monotonically increasing.  Even if you generate more than one in the same timestamp, the
       *    latter ones will sort after the former ones.  We do this by using the previous random bits
       *    but "incrementing" them by 1 (only in the case of a timestamp collision).
       */
      generatePushID = (function() {
        // Modeled after base64 web-safe chars, but ordered by ASCII.
        var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
      
        // Timestamp of last push, used to prevent local collisions if you push twice in one ms.
        var lastPushTime = 0;
      
        // We generate 72-bits of randomness which get turned into 12 characters and appended to the
        // timestamp to prevent collisions with other clients.  We store the last characters we
        // generated because in the event of a collision, we'll use those same characters except
        // "incremented" by one.
        var lastRandChars = [];
      
        return function() {
          var now = new Date().getTime();
          var duplicateTime = (now === lastPushTime);
          lastPushTime = now;
      
          var timeStampChars = new Array(8);
          for (var i = 7; i >= 0; i--) {
            timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
            // NOTE: Can't use << here because javascript will convert to int and lose the upper bits.
            now = Math.floor(now / 64);
          }
          if (now !== 0) throw new Error('We should have converted the entire timestamp.');
      
          var id = timeStampChars.join('');
      
          if (!duplicateTime) {
            for (i = 0; i < 12; i++) {
              lastRandChars[i] = Math.floor(Math.random() * 64);
            }
          } else {
            // If the timestamp hasn't changed since last push, use the same random number, except incremented by 1.
            for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
              lastRandChars[i] = 0;
            }
            lastRandChars[i]++;
          }
          for (i = 0; i < 12; i++) {
            id += PUSH_CHARS.charAt(lastRandChars[i]);
          }
          if(id.length != 20) throw new Error('Length should be 20.');
      
          return id;
        };
      })();
      

      【讨论】:

        【解决方案6】:

        您可以使用.then().push()snapshot.key 之后返回的promise 添加ObjectID 来更新记录:

        const ref = Firebase.database().ref(`/posts`);
        ref.push({ title, categories, content, timestamp})
           .then((snapshot) => {
             ref.child(snapshot.key).update({"id": snapshot.key})
           });
        

        【讨论】:

          【解决方案7】:

          如果您想在写入数据库时​​或写入数据库后获取由 firebase push() 方法生成的唯一密钥,而无需再次调用,您可以这样做:

          var reference = firebaseDatabase.ref('your/reference').push()
          
          var uniqueKey = reference.key
          
          reference.set("helllooooo")
          .then(() => {
          
          console.log(uniqueKey)
          
          
          
          // this uniqueKey will be the same key that was just add/saved to your database
          
          
          
          // can check your local console and your database, you will see the same key in both firebase and your local console
          
          
          })
          .catch(err =>
          
          console.log(err)
          
          
          });
          

          push() 方法有一个 key 属性,它提供刚刚生成的密钥,您可以在写入数据库之前、之后或期间使用它。

          【讨论】:

            【解决方案8】:

            我是怎么做到的:

            FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
            DatabaseReference ref = mFirebaseDatabase.getReference().child("users").child(uid); 
            
            String key = ref.push().getKey(); // this will fetch unique key in advance
            ref.child(key).setValue(classObject);
            

            现在您可以保留密钥以供进一步使用..

            【讨论】:

            • 这是 Java,而 OP 的代码是 Javascript/web。
            猜你喜欢
            • 1970-01-01
            • 2016-12-10
            • 1970-01-01
            • 1970-01-01
            • 2021-02-28
            • 2014-03-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多